/*
   * (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();
    }
  }
    @Override
    public void stateChanged(ChangeEvent e) {
      SubstanceCoreUtilities.testComponentStateChangeThreadingViolation(progressBar);

      if (displayTimeline != null) { // Main Change - this should be first
        // displayTimeline.abort();
      }
      int currValue = progressBar.getValue();
      int span = progressBar.getMaximum() - progressBar.getMinimum();

      int barRectWidth = progressBar.getWidth() - 2 * margin;
      int barRectHeight = progressBar.getHeight() - 2 * margin;
      int totalPixels =
          (progressBar.getOrientation() == JProgressBar.HORIZONTAL) ? barRectWidth : barRectHeight;

      int pixelDelta = (span <= 0) ? 0 : (currValue - displayedValue) * totalPixels / span;

      /*displayTimeline = new Timeline(progressBar);
      displayTimeline.addPropertyToInterpolate(Timeline
      .<Integer>property("displayedValue").from(displayedValue)
      .to(currValue).setWith(new TimelinePropertyBuilder.PropertySetter<Integer>() {
      @Override
      public void set(Object obj, String fieldName,
      Integer value) {
      displayedValue = value;
      progressBar.repaint();
      }
      }));
      displayTimeline.setEase(new Spline(0.4f));
      AnimationConfigurationManager.getInstance().configureTimeline(
      displayTimeline);*/
      boolean isInCellRenderer =
          (SwingUtilities.getAncestorOfClass(CellRendererPane.class, progressBar) != null);
      if (false) { // currValue > 0 && !isInCellRenderer && Math.abs(pixelDelta) > 5) {
        displayTimeline.play();
      } else {
        displayedValue = currValue;
        progressBar.repaint();
      }
    }
  /*
   * (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 org.jvnet.flamingo.ribbon.ui.BasicRibbonUI#paintTaskArea(java.awt.
   * Graphics , int, int, int, int)
   */
  @Override
  protected void paintTaskArea(Graphics g, int x, int y, int width, int height) {
    if (this.ribbon.getTaskCount() == 0) return;

    Graphics2D g2d = (Graphics2D) g.create();

    RibbonTask selectedTask = this.ribbon.getSelectedTask();
    JRibbonTaskToggleButton selectedTaskButton = this.taskToggleButtons.get(selectedTask);
    Rectangle selectedTaskButtonBounds = selectedTaskButton.getBounds();
    Point converted =
        SwingUtilities.convertPoint(
            selectedTaskButton.getParent(), selectedTaskButtonBounds.getLocation(), this.ribbon);
    float radius =
        SubstanceSizeUtils.getClassicButtonCornerRadius(
            SubstanceSizeUtils.getComponentFontSize(this.ribbon));

    float borderDelta = SubstanceSizeUtils.getBorderStrokeWidth() / 2.0f;

    SubstanceBorderPainter borderPainter = SubstanceCoreUtilities.getBorderPainter(this.ribbon);
    float borderThickness = SubstanceSizeUtils.getBorderStrokeWidth();

    AbstractRibbonBand band = (selectedTask.getBandCount() == 0) ? null : selectedTask.getBand(0);
    SubstanceColorScheme borderScheme =
        SubstanceColorSchemeUtilities.getColorScheme(
            band, ColorSchemeAssociationKind.BORDER, ComponentState.ENABLED);

    Rectangle taskToggleButtonsViewportBounds =
        taskToggleButtonsScrollablePanel.getView().getParent().getBounds();
    taskToggleButtonsViewportBounds.setLocation(
        SwingUtilities.convertPoint(
            taskToggleButtonsScrollablePanel,
            taskToggleButtonsViewportBounds.getLocation(),
            this.ribbon));
    int startSelectedX = Math.max(converted.x + 1, (int) taskToggleButtonsViewportBounds.getMinX());
    startSelectedX = Math.min(startSelectedX, (int) taskToggleButtonsViewportBounds.getMaxX());
    int endSelectedX =
        Math.min(
            converted.x + selectedTaskButtonBounds.width - 1,
            (int) taskToggleButtonsViewportBounds.getMaxX());
    endSelectedX = Math.max(endSelectedX, (int) taskToggleButtonsViewportBounds.getMinX());

    Shape outerContour =
        RibbonBorderShaper.getRibbonBorderOutline(
            this.ribbon,
            x + borderDelta,
            x + width - borderDelta,
            startSelectedX - borderThickness,
            endSelectedX + borderThickness,
            converted.y + borderDelta,
            y + borderDelta,
            y + height - borderDelta,
            radius);

    Shape innerContour =
        RibbonBorderShaper.getRibbonBorderOutline(
            this.ribbon,
            x + borderDelta + borderThickness,
            x + width - borderThickness - borderDelta,
            startSelectedX - borderThickness,
            endSelectedX + borderThickness,
            converted.y + borderDelta + borderThickness,
            y + borderDelta + borderThickness,
            y + height - borderThickness - borderDelta,
            radius);

    g2d.setColor(
        SubstanceColorSchemeUtilities.getColorScheme(band, ComponentState.ENABLED)
            .getBackgroundFillColor());
    g2d.clipRect(x, y, width, height + 2);
    g2d.fill(outerContour);

    // g2d.setColor(Color.red);
    // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    // RenderingHints.VALUE_ANTIALIAS_ON);
    // g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
    // RenderingHints.VALUE_STROKE_PURE);
    // g2d.setStroke(new BasicStroke(0.5f));
    // g2d.draw(outerContour);
    // g2d.setColor(Color.blue);
    // g2d.draw(innerContour);
    borderPainter.paintBorder(
        g2d,
        this.ribbon,
        width,
        height + selectedTaskButtonBounds.height + 1,
        outerContour,
        innerContour,
        borderScheme);

    // check whether the currently selected task is a contextual task
    RibbonTask selected = selectedTask;
    RibbonContextualTaskGroup contextualGroup = selected.getContextualGroup();
    if (contextualGroup != null) {
      // paint a small gradient directly below the task area
      Insets ins = this.ribbon.getInsets();
      int topY = ins.top + getTaskbarHeight();
      int bottomY = topY + 5;
      Color hueColor = contextualGroup.getHueColor();
      Paint paint =
          new GradientPaint(
              0,
              topY,
              FlamingoUtilities.getAlphaColor(
                  hueColor, (int) (255 * RibbonContextualTaskGroup.HUE_ALPHA)),
              0,
              bottomY,
              FlamingoUtilities.getAlphaColor(hueColor, 0));
      g2d.setPaint(paint);
      g2d.clip(outerContour);
      g2d.fillRect(0, topY, width, bottomY - topY + 1);
    }

    // paint outlines of the contextual task groups
    // paintContextualTaskGroupsOutlines(g);

    g2d.dispose();
  }
 /*
  * (non-Javadoc)
  *
  * @see javax.swing.plaf.ComponentUI#createUI(javax.swing.JComponent)
  */
 public static ComponentUI createUI(JComponent comp) {
   SubstanceCoreUtilities.testComponentCreationThreadingViolation(comp);
   return new SubstanceRibbonUI();
 }
 /**
  * Returns the collection of color schemes in the specified URL.
  *
  * @param resourceName Name of the resource containing the description of Substance color schemes.
  * @return The collection of color schemes in the specified URL.
  * @since version 6.0
  */
 public static ColorSchemes getColorSchemes(String resourceName) {
   ClassLoader cl = SubstanceCoreUtilities.getClassLoaderForResources();
   return SubstanceColorSchemeUtilities.getColorSchemes(cl.getResource(resourceName));
 }