@Override
  protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) {
    AbstractButton b = (AbstractButton) c;
    ButtonModel model = b.getModel();
    Icon icon = b.getIcon();
    Icon tmpIcon = null;
    Icon shadowIcon = null;
    boolean borderHasPressedCue = borderHasPressedCue(b);

    if (icon == null) {
      return;
    }

    if (!model.isEnabled()) {
      if (model.isSelected()) {
        tmpIcon = (Icon) b.getDisabledSelectedIcon();
      } else {
        tmpIcon = (Icon) b.getDisabledIcon();
      }
    } else if (model.isPressed() && model.isArmed()) {
      tmpIcon = (Icon) b.getPressedIcon();
      if (tmpIcon != null) {
        // revert back to 0 offset
        clearTextShiftOffset();
      } else if (icon != null && icon instanceof ImageIcon && !borderHasPressedCue) {
        // Create an icon on the fly.
        // Note: This is only needed for borderless buttons, which
        //       have no other way to provide feedback about the pressed
        //       state.
        tmpIcon =
            new ImageIcon(HalfbrightFilter.createHalfbrightImage(((ImageIcon) icon).getImage()));
        shadowIcon = new ImageIcon(ShadowFilter.createShadowImage(((ImageIcon) icon).getImage()));
      }
    } else if (b.isRolloverEnabled() && model.isRollover()) {
      if (model.isSelected()) {
        tmpIcon = b.getRolloverSelectedIcon();
        if (tmpIcon == null) {
          tmpIcon = b.getSelectedIcon();
        }
      } else {
        tmpIcon = (Icon) b.getRolloverIcon();
      }
    } else if (model.isSelected()) {
      tmpIcon = b.getSelectedIcon();
    }

    if (tmpIcon != null) {
      icon = tmpIcon;
    }

    if (model.isPressed() && model.isArmed()) {
      if (shadowIcon != null) {
        shadowIcon.paintIcon(
            c, g, iconRect.x + getTextShiftOffset(), iconRect.y + getTextShiftOffset() + 1);
      }
      icon.paintIcon(c, g, iconRect.x + getTextShiftOffset(), iconRect.y + getTextShiftOffset());
    } else {
      icon.paintIcon(c, g, iconRect.x, iconRect.y);
    }
  }
  protected Rectangle rectangleForArrowIcon() {
    Rectangle b = comboBox.getBounds();
    Border border = comboBox.getBorder();
    Insets in;
    if (border != null) {
      in = border.getBorderInsets(comboBox);
    } else {
      in = new Insets(0, 0, 0, 0);
    }
    b.x = in.left;
    b.y = in.top;
    b.width -= (in.left + in.right);
    b.height -= (in.top + in.bottom);

    if (MotifGraphicsUtils.isLeftToRight(comboBox)) {
      b.x = b.x + b.width - HORIZ_MARGIN - arrowIcon.getIconWidth();
    } else {
      b.x += HORIZ_MARGIN;
    }
    b.y = b.y + (b.height - arrowIcon.getIconHeight()) / 2;
    b.width = arrowIcon.getIconWidth();
    b.height = arrowIcon.getIconHeight();
    return b;
  }
  public void paint(Graphics g, JComponent c) {
    boolean hasFocus = comboBox.hasFocus();
    Rectangle r;

    if (comboBox.isEnabled()) {
      g.setColor(comboBox.getBackground());
    } else {
      g.setColor(UIManager.getColor("ComboBox.disabledBackground"));
    }
    g.fillRect(0, 0, c.getWidth(), c.getHeight());

    if (!comboBox.isEditable()) {
      r = rectangleForCurrentValue();
      paintCurrentValue(g, r, hasFocus);
    }
    r = rectangleForArrowIcon();
    arrowIcon.paintIcon(c, g, r.x, r.y);
    if (!comboBox.isEditable()) {
      Border border = comboBox.getBorder();
      Insets in;
      if (border != null) {
        in = border.getBorderInsets(comboBox);
      } else {
        in = new Insets(0, 0, 0, 0);
      }
      // Draw the separation
      if (MotifGraphicsUtils.isLeftToRight(comboBox)) {
        r.x -= (HORIZ_MARGIN + 2);
      } else {
        r.x += r.width + HORIZ_MARGIN + 1;
      }
      r.y = in.top;
      r.width = 1;
      r.height = comboBox.getBounds().height - in.bottom - in.top;
      g.setColor(UIManager.getColor("controlShadow"));
      g.fillRect(r.x, r.y, r.width, r.height);
      r.x++;
      g.setColor(UIManager.getColor("controlHighlight"));
      g.fillRect(r.x, r.y, r.width, r.height);
    }
  }
  /**
   * Compute and return the location of the icons origin, the location of origin of the text
   * baseline, and a possibly clipped version of the compound labels string. Locations are computed
   * relative to the viewR rectangle.
   */
  private static String layoutMenuItem(
      JComponent c,
      FontMetrics fm,
      String text,
      FontMetrics fmAccel,
      String acceleratorText,
      Icon icon,
      Icon checkIcon,
      Icon arrowIcon,
      int verticalAlignment,
      int horizontalAlignment,
      int verticalTextPosition,
      int horizontalTextPosition,
      Rectangle viewR,
      Rectangle iconR,
      Rectangle textR,
      Rectangle acceleratorR,
      Rectangle checkIconR,
      Rectangle arrowIconR,
      int textIconGap,
      int menuItemGap) {

    SwingUtilities.layoutCompoundLabel(
        c,
        fm,
        text,
        icon,
        verticalAlignment,
        horizontalAlignment,
        verticalTextPosition,
        horizontalTextPosition,
        viewR,
        iconR,
        textR,
        textIconGap);

    /* Initialize the acceelratorText bounds rectangle textR.  If a null
     * or and empty String was specified we substitute "" here
     * and use 0,0,0,0 for acceleratorTextR.
     */
    if ((acceleratorText == null) || acceleratorText.equals("")) {
      acceleratorR.width = acceleratorR.height = 0;
      acceleratorText = "";
    } else {
      acceleratorR.width = SwingUtilities2.stringWidth(c, fmAccel, acceleratorText);
      acceleratorR.height = fmAccel.getHeight();
    }

    /* Initialize the checkIcon bounds rectangle checkIconR.
     */

    if (checkIcon != null) {
      checkIconR.width = checkIcon.getIconWidth();
      checkIconR.height = checkIcon.getIconHeight();
    } else {
      checkIconR.width = checkIconR.height = 0;
    }

    /* Initialize the arrowIcon bounds rectangle arrowIconR.
     */

    if (arrowIcon != null) {
      arrowIconR.width = arrowIcon.getIconWidth();
      arrowIconR.height = arrowIcon.getIconHeight();
    } else {
      arrowIconR.width = arrowIconR.height = 0;
    }

    Rectangle labelR = iconR.union(textR);
    if (MotifGraphicsUtils.isLeftToRight(c)) {
      textR.x += checkIconR.width + menuItemGap;
      iconR.x += checkIconR.width + menuItemGap;

      // Position the Accelerator text rect
      acceleratorR.x = viewR.x + viewR.width - arrowIconR.width - menuItemGap - acceleratorR.width;

      // Position the Check and Arrow Icons
      checkIconR.x = viewR.x;
      arrowIconR.x = viewR.x + viewR.width - menuItemGap - arrowIconR.width;
    } else {
      textR.x -= (checkIconR.width + menuItemGap);
      iconR.x -= (checkIconR.width + menuItemGap);

      // Position the Accelerator text rect
      acceleratorR.x = viewR.x + arrowIconR.width + menuItemGap;

      // Position the Check and Arrow Icons
      checkIconR.x = viewR.x + viewR.width - checkIconR.width;
      arrowIconR.x = viewR.x + menuItemGap;
    }

    // Align the accelertor text and the check and arrow icons vertically
    // with the center of the label rect.
    acceleratorR.y = labelR.y + (labelR.height / 2) - (acceleratorR.height / 2);
    arrowIconR.y = labelR.y + (labelR.height / 2) - (arrowIconR.height / 2);
    checkIconR.y = labelR.y + (labelR.height / 2) - (checkIconR.height / 2);

    /*
    System.out.println("Layout: v=" +viewR+"  c="+checkIconR+" i="+
    iconR+" t="+textR+" acc="+acceleratorR+" a="+arrowIconR);
    */
    return text;
  }
  /**
   * This method is not being used to paint menu item since 6.0 This code left for compatibility
   * only. Do not use or override it, this will not cause any visible effect.
   */
  public static void paintMenuItem(
      Graphics g,
      JComponent c,
      Icon checkIcon,
      Icon arrowIcon,
      Color background,
      Color foreground,
      int defaultTextIconGap) {

    JMenuItem b = (JMenuItem) c;
    ButtonModel model = b.getModel();

    Dimension size = b.getSize();
    Insets i = c.getInsets();

    Rectangle viewRect = new Rectangle(size);

    viewRect.x += i.left;
    viewRect.y += i.top;
    viewRect.width -= (i.right + viewRect.x);
    viewRect.height -= (i.bottom + viewRect.y);

    Rectangle iconRect = new Rectangle();
    Rectangle textRect = new Rectangle();
    Rectangle acceleratorRect = new Rectangle();
    Rectangle checkRect = new Rectangle();
    Rectangle arrowRect = new Rectangle();

    Font holdf = g.getFont();
    Font f = c.getFont();
    g.setFont(f);
    FontMetrics fm = SwingUtilities2.getFontMetrics(c, g, f);
    FontMetrics fmAccel =
        SwingUtilities2.getFontMetrics(c, g, UIManager.getFont("MenuItem.acceleratorFont"));

    if (c.isOpaque()) {
      if (model.isArmed() || (c instanceof JMenu && model.isSelected())) {
        g.setColor(background);
      } else {
        g.setColor(c.getBackground());
      }
      g.fillRect(0, 0, size.width, size.height);
    }

    // get Accelerator text
    KeyStroke accelerator = b.getAccelerator();
    String acceleratorText = "";
    if (accelerator != null) {
      int modifiers = accelerator.getModifiers();
      if (modifiers > 0) {
        acceleratorText = KeyEvent.getKeyModifiersText(modifiers);
        acceleratorText += "+";
      }
      acceleratorText += KeyEvent.getKeyText(accelerator.getKeyCode());
    }

    // layout the text and icon
    String text =
        layoutMenuItem(
            c,
            fm,
            b.getText(),
            fmAccel,
            acceleratorText,
            b.getIcon(),
            checkIcon,
            arrowIcon,
            b.getVerticalAlignment(),
            b.getHorizontalAlignment(),
            b.getVerticalTextPosition(),
            b.getHorizontalTextPosition(),
            viewRect,
            iconRect,
            textRect,
            acceleratorRect,
            checkRect,
            arrowRect,
            b.getText() == null ? 0 : defaultTextIconGap,
            defaultTextIconGap);

    // Paint the Check
    Color holdc = g.getColor();
    if (checkIcon != null) {
      if (model.isArmed() || (c instanceof JMenu && model.isSelected())) g.setColor(foreground);
      checkIcon.paintIcon(c, g, checkRect.x, checkRect.y);
      g.setColor(holdc);
    }

    // Paint the Icon
    if (b.getIcon() != null) {
      Icon icon;
      if (!model.isEnabled()) {
        icon = (Icon) b.getDisabledIcon();
      } else if (model.isPressed() && model.isArmed()) {
        icon = (Icon) b.getPressedIcon();
        if (icon == null) {
          // Use default icon
          icon = (Icon) b.getIcon();
        }
      } else {
        icon = (Icon) b.getIcon();
      }

      if (icon != null) {
        icon.paintIcon(c, g, iconRect.x, iconRect.y);
      }
    }

    // Draw the Text
    if (text != null && !text.equals("")) {
      // Once BasicHTML becomes public, use BasicHTML.propertyKey
      // instead of the hardcoded string below!
      View v = (View) c.getClientProperty("html");
      if (v != null) {
        v.paint(g, textRect);
      } else {
        int mnemIndex = b.getDisplayedMnemonicIndex();

        if (!model.isEnabled()) {
          // *** paint the text disabled
          g.setColor(b.getBackground().brighter());
          SwingUtilities2.drawStringUnderlineCharAt(
              b, g, text, mnemIndex, textRect.x, textRect.y + fmAccel.getAscent());
          g.setColor(b.getBackground().darker());
          SwingUtilities2.drawStringUnderlineCharAt(
              b, g, text, mnemIndex, textRect.x - 1, textRect.y + fmAccel.getAscent() - 1);

        } else {
          // *** paint the text normally
          if (model.isArmed() || (c instanceof JMenu && model.isSelected())) {
            g.setColor(foreground);
          } else {
            g.setColor(b.getForeground());
          }
          SwingUtilities2.drawStringUnderlineCharAt(
              b, g, text, mnemIndex, textRect.x, textRect.y + fm.getAscent());
        }
      }
    }

    // Draw the Accelerator Text
    if (acceleratorText != null && !acceleratorText.equals("")) {

      // Get the maxAccWidth from the parent to calculate the offset.
      int accOffset = 0;
      Container parent = b.getParent();
      if (parent != null && parent instanceof JComponent) {
        JComponent p = (JComponent) parent;
        Integer maxValueInt = (Integer) p.getClientProperty(MotifGraphicsUtils.MAX_ACC_WIDTH);
        int maxValue = maxValueInt != null ? maxValueInt.intValue() : acceleratorRect.width;

        // Calculate the offset, with which the accelerator texts will be drawn with.
        accOffset = maxValue - acceleratorRect.width;
      }

      g.setFont(UIManager.getFont("MenuItem.acceleratorFont"));
      if (!model.isEnabled()) {
        // *** paint the acceleratorText disabled
        g.setColor(b.getBackground().brighter());
        SwingUtilities2.drawString(
            c,
            g,
            acceleratorText,
            acceleratorRect.x - accOffset,
            acceleratorRect.y + fm.getAscent());
        g.setColor(b.getBackground().darker());
        SwingUtilities2.drawString(
            c,
            g,
            acceleratorText,
            acceleratorRect.x - accOffset - 1,
            acceleratorRect.y + fm.getAscent() - 1);
      } else {
        // *** paint the acceleratorText normally
        if (model.isArmed() || (c instanceof JMenu && model.isSelected())) {
          g.setColor(foreground);
        } else {
          g.setColor(b.getForeground());
        }
        SwingUtilities2.drawString(
            c,
            g,
            acceleratorText,
            acceleratorRect.x - accOffset,
            acceleratorRect.y + fmAccel.getAscent());
      }
    }

    // Paint the Arrow
    if (arrowIcon != null) {
      if (model.isArmed() || (c instanceof JMenu && model.isSelected())) g.setColor(foreground);
      if (!(b.getParent() instanceof JMenuBar)) arrowIcon.paintIcon(c, g, arrowRect.x, arrowRect.y);
    }

    g.setColor(holdc);
    g.setFont(holdf);
  }
  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();
  }
 public int iconAreaWidth() {
   if (comboBox.isEditable()) return arrowIcon.getIconWidth() + (2 * HORIZ_MARGIN);
   else return arrowIcon.getIconWidth() + (3 * HORIZ_MARGIN) + 2;
 }