/** Synchronizes the tooltip of the close button. */
 protected void syncCloseButtonTooltip() {
   if (SubstanceCoreUtilities.isInternalFrameModified(this.frame)) {
     this.closeButton.setToolTipText(
         SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.close")
             + " ["
             + SubstanceCoreUtilities.getResourceBundle(frame)
                 .getString("Tooltip.contentsNotSaved")
             + "]");
   } else {
     this.closeButton.setToolTipText(
         SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.close"));
   }
   this.closeButton.repaint();
 }
  public DecorationAreaType getThisDecorationType() {
    DecorationAreaType dat = SubstanceLookAndFeel.getDecorationType(this);
    if (dat == DecorationAreaType.PRIMARY_TITLE_PANE) {
      return SubstanceCoreUtilities.isPaintRootPaneActivated(frame.getRootPane())
          ? DecorationAreaType.PRIMARY_TITLE_PANE
          : DecorationAreaType.PRIMARY_TITLE_PANE_INACTIVE;
    } else if (dat == DecorationAreaType.SECONDARY_TITLE_PANE) {
      return SubstanceCoreUtilities.isPaintRootPaneActivated(frame.getRootPane())
          ? DecorationAreaType.SECONDARY_TITLE_PANE
          : DecorationAreaType.SECONDARY_TITLE_PANE_INACTIVE;

    } else {
      return dat;
    }
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * org.jvnet.flamingo.common.ui.BasicCommandButtonUI#getPreferredSize(javax
   * .swing.JComponent)
   */
  @Override
  public Dimension getPreferredSize(JComponent c) {
    AbstractCommandButton button = (AbstractCommandButton) c;
    SubstanceButtonShaper shaper = SubstanceCoreUtilities.getButtonShaper(button);

    Dimension superPref = super.getPreferredSize(button);
    if (superPref == null) return null;

    if (shaper == null) return superPref;

    // fix for issue 35 on Flamingo - do not enforce
    // min size on buttons in the ribbon
    // Additional fix - buttons with popup action should
    // not have min size enforced as well
    // Additional fix - buttons in popup menus and breadcrumb bars should
    // not have min size enforced
    if ((button.getDisplayState() == CommandButtonDisplayState.MEDIUM)
        && (SwingUtilities.getAncestorOfClass(AbstractRibbonBand.class, button) == null)
        && (SwingUtilities.getAncestorOfClass(JBreadcrumbBar.class, button) == null)
        && (SwingUtilities.getAncestorOfClass(JCommandPopupMenu.class, button) == null)) {
      JButton dummy = new JButton(button.getText(), button.getIcon());
      Dimension result = shaper.getPreferredSize(dummy, superPref);
      if (FlamingoUtilities.hasPopupAction(button)) {
        result.width = superPref.width;
      }
      return result;
    }
    return superPref;
  }
  /*
   * (non-Javadoc)
   *
   * @see javax.swing.Icon#paintIcon(java.awt.Component, java.awt.Graphics,
   * int, int)
   */
  @Override
  public void paintIcon(Component c, Graphics g, int x, int y) {
    // check if loading
    if (this.delegate instanceof AsynchronousLoading) {
      AsynchronousLoading asyncDelegate = (AsynchronousLoading) this.delegate;
      // if the delegate is still loading - do nothing
      if (asyncDelegate.isLoading()) return;
    }

    SubstanceColorScheme scheme =
        SubstanceColorSchemeUtilities.getColorScheme(c, ComponentState.DISABLED_UNSELECTED);
    HashMapKey key =
        SubstanceCoreUtilities.getHashKey(
            this.getIconWidth(), this.getIconHeight(), scheme.getDisplayName());

    BufferedImage filtered = this.cachedImages.get(key);
    if (filtered == null) {
      BufferedImage offscreen =
          FlamingoUtilities.getBlankImage(this.getIconWidth(), this.getIconHeight());
      Graphics2D g2d = offscreen.createGraphics();
      this.delegate.paintIcon(c, g2d, 0, 0);
      g2d.dispose();
      filtered = SubstanceImageCreator.getColorSchemeImage(offscreen, scheme, 0.5f);
      this.cachedImages.put(key, filtered);
    }
    g.drawImage(filtered, x, y, null);
  }
  /*
   * (non-Javadoc)
   *
   * @see
   * org.jvnet.flamingo.common.ui.BasicCommandButtonUI#paintButtonBackground
   * (java.awt.Graphics, java.awt.Rectangle)
   */
  @Override
  protected void paintButtonBackground(Graphics graphics, Rectangle toFill) {
    if (SubstanceCoreUtilities.isButtonNeverPainted(this.commandButton)) return;

    ButtonModel actionModel = this.commandButton.getActionModel();
    PopupButtonModel popupModel = ((JCommandButton) this.commandButton).getPopupModel();
    Rectangle actionArea = this.getLayoutInfo().actionClickArea;
    Rectangle popupArea = this.getLayoutInfo().popupClickArea;

    BufferedImage fullAlphaBackground =
        CommandButtonBackgroundDelegate.getCombinedCommandButtonBackground(
            this.commandButton, actionModel, actionArea, popupModel, popupArea);

    // Two special cases here:
    // 1. Button has flat appearance and doesn't show the popup
    // 2. Button is disabled.
    // For both cases, we need to set custom translucency.
    boolean isFlat =
        this.commandButton.isFlat()
            && !((JCommandButton) this.commandButton).getPopupModel().isPopupShowing();
    boolean isSpecial = isFlat || !this.commandButton.isEnabled();
    float extraAlpha = 1.0f;
    if (isSpecial) {
      if (isFlat) {
        float extraActionAlpha = 0.0f;
        for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> activeEntry :
            getActionTransitionTracker().getModelStateInfo().getStateContributionMap().entrySet()) {
          ComponentState activeState = activeEntry.getKey();
          if (activeState.isDisabled()) continue;
          if (activeState == ComponentState.ENABLED) continue;
          extraActionAlpha += activeEntry.getValue().getContribution();
        }
        float extraPopupAlpha = 0.0f;
        for (Map.Entry<ComponentState, StateTransitionTracker.StateContributionInfo> activeEntry :
            getPopupTransitionTracker().getModelStateInfo().getStateContributionMap().entrySet()) {
          ComponentState activeState = activeEntry.getKey();
          if (activeState.isDisabled()) continue;
          if (activeState == ComponentState.ENABLED) continue;
          extraPopupAlpha += activeEntry.getValue().getContribution();
        }
        extraAlpha = Math.max(extraActionAlpha, extraPopupAlpha);
      } else {
        ComponentState actionAreaState = ComponentState.getState(actionModel, this.commandButton);
        if (actionAreaState.isDisabled()) {
          extraAlpha = SubstanceColorSchemeUtilities.getAlpha(this.commandButton, actionAreaState);
        }
      }
    }
    // System.out.println(extraAlpha);
    extraAlpha = Math.min(1.0f, extraAlpha);
    if (extraAlpha > 0.0f) {
      Graphics2D g2d = (Graphics2D) graphics.create();
      g2d.setComposite(
          LafWidgetUtilities.getAlphaComposite(this.commandButton, extraAlpha, graphics));
      g2d.drawImage(fullAlphaBackground, 0, 0, null);
      g2d.dispose();
    }
  }
 /*
  * (non-Javadoc)
  *
  * @see javax.swing.plaf.basic.BasicInternalFrameTitlePane#installDefaults()
  */
 @Override
 protected void installDefaults() {
   super.installDefaults();
   if (SubstanceLookAndFeel.isCurrentLookAndFeel()) {
     this.setForeground(
         SubstanceColorUtilities.getForegroundColor(
             SubstanceCoreUtilities.getSkin(this.frame)
                 .getActiveColorScheme(getThisDecorationType())));
   }
   // this.wasClosable = this.frame.isClosable();
 }
 /** Uninstalls <code>this</code> title pane. */
 public void uninstall() {
   if ((this.menuBar != null) && (this.menuBar.getMenuCount() > 0)) {
     MenuBarUI menuBarUI = this.menuBar.getUI();
     if (menuBarUI instanceof SubstanceMenuBarUI) {
       SubstanceMenuBarUI ui = (SubstanceMenuBarUI) menuBarUI;
       if (ui.getMenuBar() == this.menuBar) menuBarUI.uninstallUI(this.menuBar);
     }
     SubstanceCoreUtilities.uninstallMenu(this.menuBar.getMenu(0));
     this.remove(menuBar);
     // fix for issue 362 - remove the buttons so that we don't
     // have duplicate buttons on internal frames in reparented
     // desktop panes
     this.remove(maxButton);
     this.remove(closeButton);
     this.remove(iconButton);
   }
   this.uninstallListeners();
   this.putClientProperty(UNINSTALLED, Boolean.TRUE);
 }
  /*
   * (non-Javadoc)
   *
   * @see
   * org.jvnet.flamingo.common.ui.BasicCommandButtonUI#paintButtonIcon(java
   * .awt.Graphics, java.awt.Rectangle)
   */
  @Override
  protected void paintButtonIcon(Graphics g, Rectangle iconRect) {
    JCommandButton jcb = (JCommandButton) this.commandButton;
    Icon regular = jcb.getIcon();
    if (toUseDisabledIcon()
        && (jcb.getDisabledIcon() != null)
        && ((regular != null) && !regular.getClass().isAnnotationPresent(TransitionAware.class)))
      regular = jcb.getDisabledIcon();

    if ((iconRect == null)
        || (regular == null)
        || (iconRect.width == 0)
        || (iconRect.height == 0)) {
      return;
    }

    boolean useThemed = SubstanceCoreUtilities.useThemedDefaultIcon(this.commandButton);
    if (regular != null) {
      Graphics2D g2d = (Graphics2D) g.create();

      GhostPaintingUtils.paintGhostIcon(g2d, jcb, regular, iconRect);
      g2d.setComposite(LafWidgetUtilities.getAlphaComposite(jcb, g));

      if (!useThemed) {
        regular.paintIcon(jcb, g2d, iconRect.x, iconRect.y);
      } else {
        StateTransitionTracker tracker =
            this.substanceVisualStateTracker.getActionStateTransitionTracker();
        ButtonModel model = commandButton.getActionModel();
        if (jcb.getCommandButtonKind() == CommandButtonKind.POPUP_ONLY) {
          tracker = this.substanceVisualStateTracker.getPopupStateTransitionTracker();
          model = jcb.getPopupModel();
        }
        CommandButtonBackgroundDelegate.paintThemedCommandButtonIcon(
            g2d, iconRect, jcb, regular, model, tracker);
      }
      g2d.dispose();
    }
  }
 /*
  * (non-Javadoc)
  *
  * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
  */
 public static ComponentUI createUI(JComponent comp) {
   SubstanceCoreUtilities.testComponentCreationThreadingViolation(comp);
   return new SubstanceCommandButtonUI((JCommandButton) comp);
 }
  /*
   * (non-Javadoc)
   *
   * @see javax.swing.plaf.basic.BasicInternalFrameTitlePane#setButtonIcons()
   */
  @Override
  protected void setButtonIcons() {
    super.setButtonIcons();
    if (!SubstanceLookAndFeel.isCurrentLookAndFeel()) return;

    Icon restoreIcon =
        new TransitionAwareIcon(
            this.maxButton,
            new TransitionAwareIcon.Delegate() {
              @Override
              public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
                return SubstanceIconFactory.getTitlePaneIcon(
                    SubstanceIconFactory.IconKind.RESTORE,
                    scheme,
                    SubstanceCoreUtilities.getSkin(SubstanceInternalFrameTitlePane.this)
                        .getBackgroundColorScheme(getThisDecorationType()));
              }
            },
            "substance.internalFrame.restoreIcon");
    Icon maximizeIcon =
        new TransitionAwareIcon(
            this.maxButton,
            new TransitionAwareIcon.Delegate() {
              @Override
              public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
                return SubstanceIconFactory.getTitlePaneIcon(
                    SubstanceIconFactory.IconKind.MAXIMIZE,
                    scheme,
                    SubstanceCoreUtilities.getSkin(SubstanceInternalFrameTitlePane.this)
                        .getBackgroundColorScheme(getThisDecorationType()));
              }
            },
            "substance.internalFrame.maxIcon");
    Icon minimizeIcon =
        new TransitionAwareIcon(
            this.iconButton,
            new TransitionAwareIcon.Delegate() {
              @Override
              public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
                return SubstanceIconFactory.getTitlePaneIcon(
                    SubstanceIconFactory.IconKind.MINIMIZE,
                    scheme,
                    SubstanceCoreUtilities.getSkin(SubstanceInternalFrameTitlePane.this)
                        .getBackgroundColorScheme(getThisDecorationType()));
              }
            },
            "substance.internalFrame.minIcon");
    Icon closeIcon =
        new TransitionAwareIcon(
            this.closeButton,
            new TransitionAwareIcon.Delegate() {
              @Override
              public Icon getColorSchemeIcon(SubstanceColorScheme scheme) {
                return SubstanceIconFactory.getTitlePaneIcon(
                    SubstanceIconFactory.IconKind.CLOSE,
                    scheme,
                    SubstanceCoreUtilities.getSkin(SubstanceInternalFrameTitlePane.this)
                        .getBackgroundColorScheme(getThisDecorationType()));
              }
            },
            "substance.internalFrame.closeIcon");
    if (this.frame.isIcon()) {
      this.iconButton.setIcon(restoreIcon);
      this.iconButton.setToolTipText(
          SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.restore"));
      this.maxButton.setIcon(maximizeIcon);
      this.maxButton.setToolTipText(
          SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.maximize"));
    } else {
      this.iconButton.setIcon(minimizeIcon);
      this.iconButton.setToolTipText(
          SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.iconify"));
      if (this.frame.isMaximum()) {
        this.maxButton.setIcon(restoreIcon);
        this.maxButton.setToolTipText(
            SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.restore"));
      } else {
        this.maxButton.setIcon(maximizeIcon);
        this.maxButton.setToolTipText(
            SubstanceCoreUtilities.getResourceBundle(frame).getString("SystemMenu.maximize"));
      }
    }
    if (closeIcon != null) {
      this.closeButton.setIcon(closeIcon);
      syncCloseButtonTooltip();
    }
  }
  /*
   * (non-Javadoc)
   *
   * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
   */
  @Override
  public void paintComponent(Graphics g) {
    // if (this.isPalette) {
    // this.paintPalette(g);
    // return;
    // }

    DecorationAreaType decorationType = getThisDecorationType();

    Graphics2D graphics = (Graphics2D) g.create();
    // Desktop icon is translucent.
    final float coef = (this.getParent() instanceof JDesktopIcon) ? 0.6f : 1.0f;
    graphics.setComposite(LafWidgetUtilities.getAlphaComposite(this.frame, coef, g));

    boolean leftToRight = this.frame.getComponentOrientation().isLeftToRight();

    int width = this.getWidth();
    int height = this.getHeight() + 2;

    SubstanceColorScheme scheme =
        SubstanceCoreUtilities.getSkin(this.frame).getEnabledColorScheme(decorationType);
    JInternalFrame hostFrame =
        (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class, this);
    JComponent hostForColorization = hostFrame;
    if (hostFrame == null) {
      // try desktop icon
      JDesktopIcon desktopIcon =
          (JDesktopIcon) SwingUtilities.getAncestorOfClass(JDesktopIcon.class, this);
      if (desktopIcon != null) hostFrame = desktopIcon.getInternalFrame();
      hostForColorization = desktopIcon;
    }
    // if ((hostFrame != null) && SubstanceCoreUtilities.hasColorization(
    // this)) {
    Color backgr = hostFrame.getBackground();
    if (!(backgr instanceof UIResource)) {
      double colorization = SubstanceCoreUtilities.getColorizationFactor(hostForColorization);
      scheme = ShiftColorScheme.getShiftedScheme(scheme, backgr, colorization, null, 0.0);
    }
    // }
    String theTitle = this.frame.getTitle();

    // offset of border
    int xOffset;
    int leftEnd;
    int rightEnd;

    if (leftToRight) {
      xOffset = 5;
      Icon icon = this.frame.getFrameIcon();
      if (icon != null) {
        xOffset += icon.getIconWidth() + 5;
      }

      leftEnd = (this.menuBar == null) ? 0 : (this.menuBar.getWidth() + 5);
      xOffset += leftEnd;
      if (icon != null) leftEnd += (icon.getIconWidth() + 5);

      rightEnd = width - 5;

      // find the leftmost button for the right end
      AbstractButton leftmostButton = null;
      if (this.frame.isIconifiable()) {
        leftmostButton = this.iconButton;
      } else {
        if (this.frame.isMaximizable()) {
          leftmostButton = this.maxButton;
        } else {
          if (this.frame.isClosable()) {
            leftmostButton = this.closeButton;
          }
        }
      }

      if (leftmostButton != null) {
        Rectangle rect = leftmostButton.getBounds();
        rightEnd = rect.getBounds().x - 5;
      }
      if (theTitle != null) {
        FontMetrics fm = this.frame.getFontMetrics(graphics.getFont());
        int titleWidth = rightEnd - leftEnd;
        String clippedTitle = SubstanceCoreUtilities.clipString(fm, titleWidth, theTitle);
        // show tooltip with full title only if necessary
        if (theTitle.equals(clippedTitle)) this.setToolTipText(null);
        else this.setToolTipText(theTitle);
        theTitle = clippedTitle;
      }
    } else {
      xOffset = width - 5;

      Icon icon = this.frame.getFrameIcon();
      if (icon != null) {
        xOffset -= (icon.getIconWidth() + 5);
      }

      rightEnd = (this.menuBar == null) ? xOffset : xOffset - this.menuBar.getWidth() - 5;

      // find the rightmost button for the left end
      AbstractButton rightmostButton = null;
      if (this.frame.isIconifiable()) {
        rightmostButton = this.iconButton;
      } else {
        if (this.frame.isMaximizable()) {
          rightmostButton = this.maxButton;
        } else {
          if (this.frame.isClosable()) {
            rightmostButton = this.closeButton;
          }
        }
      }

      leftEnd = 5;
      if (rightmostButton != null) {
        Rectangle rect = rightmostButton.getBounds();
        leftEnd = rect.getBounds().x + 5;
      }
      if (theTitle != null) {
        FontMetrics fm = this.frame.getFontMetrics(graphics.getFont());
        int titleWidth = rightEnd - leftEnd;
        String clippedTitle = SubstanceCoreUtilities.clipString(fm, titleWidth, theTitle);
        // show tooltip with full title only if necessary
        if (theTitle.equals(clippedTitle)) {
          this.setToolTipText(null);
        } else {
          this.setToolTipText(theTitle);
        }
        theTitle = clippedTitle;
        xOffset = rightEnd - fm.stringWidth(theTitle);
      }
    }

    BackgroundPaintingUtils.update(
        graphics, SubstanceInternalFrameTitlePane.this, false, decorationType);
    // DecorationPainterUtils.paintDecorationBackground(graphics,
    // SubstanceInternalFrameTitlePane.this, false);

    // draw the title (if needed)
    if (theTitle != null) {
      JRootPane rootPane = this.getRootPane();
      FontMetrics fm = rootPane.getFontMetrics(graphics.getFont());
      int yOffset = ((height - fm.getHeight()) / 2) + fm.getAscent();

      SubstanceTextUtilities.paintTextWithDropShadow(
          this,
          graphics,
          SubstanceColorUtilities.getForegroundColor(scheme),
          theTitle,
          width,
          height,
          xOffset,
          yOffset);
    }

    Icon icon = this.frame.getFrameIcon();
    if (icon != null) {
      if (leftToRight) {
        int iconY = ((height / 2) - (icon.getIconHeight() / 2));
        icon.paintIcon(this.frame, graphics, 5, iconY);
      } else {
        int iconY = ((height / 2) - (icon.getIconHeight() / 2));
        icon.paintIcon(this.frame, graphics, width - 5 - icon.getIconWidth(), iconY);
      }
    }

    graphics.dispose();
  }