@Override
    public void paintComponent(Graphics g) {
      super.paintComponent(g);

      AnAction action = getAction();
      if (action instanceof ActivateCard) {
        Rectangle bounds = getBounds();

        Icon icon = AllIcons.Actions.Forward; // AllIcons.Icons.Ide.NextStepGrayed;
        int y = (bounds.height - icon.getIconHeight()) / 2;
        int x = bounds.width - icon.getIconWidth() - 15;

        if (getPopState() == POPPED) {
          final GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
          g.setColor(WelcomeScreenColors.CAPTION_BACKGROUND);
          g.fillOval(x - 3, y - 3, icon.getIconWidth() + 6, icon.getIconHeight() + 6);

          g.setColor(WelcomeScreenColors.GROUP_ICON_BORDER_COLOR);
          g.drawOval(x - 3, y - 3, icon.getIconWidth() + 6, icon.getIconHeight() + 6);
          config.restore();
        } else {
          icon = IconLoader.getDisabledIcon(icon);
        }

        icon.paintIcon(this, g, x, y);
      }
    }
  @Nullable
  private static Icon getAquaMenuDisabledIcon() {
    final Icon arrowIcon = (Icon) UIManager.get("Menu.arrowIcon");
    if (arrowIcon != null) {
      return IconLoader.getDisabledIcon(arrowIcon);
    }

    return null;
  }
 public void propertyChange(final PropertyChangeEvent e) {
   final String name = e.getPropertyName();
   if (ToolWindowEx.PROP_AVAILABLE.equals(name)) {
     updateState();
   } else if (ToolWindowEx.PROP_TITLE.equals(name)) {
     updateText();
   } else if (ToolWindowEx.PROP_ICON.equals(name)) {
     final Icon icon = (Icon) e.getNewValue();
     final Icon disabledIcon = IconLoader.getDisabledIcon(icon);
     setIcon(icon);
     setDisabledIcon(disabledIcon);
   }
 }
 private void updateIcon(AnAction action) {
   if (action instanceof Toggleable && myPresentation.getIcon() == null) {
     action.update(myEvent);
     if (Boolean.TRUE.equals(
         myEvent.getPresentation().getClientProperty(Toggleable.SELECTED_PROPERTY))) {
       setIcon(ourCheckedIcon);
       setDisabledIcon(IconLoader.getDisabledIcon(ourCheckedIcon));
     } else {
       setIcon(ourUncheckedIcon);
       setDisabledIcon(IconLoader.getDisabledIcon(ourUncheckedIcon));
     }
   } else {
     if (!SystemInfo.isMac || UISettings.getInstance().SHOW_ICONS_IN_MENUS) {
       Icon icon = myPresentation.getIcon();
       setIcon(icon);
       if (myPresentation.getDisabledIcon() != null) {
         setDisabledIcon(myPresentation.getDisabledIcon());
       } else {
         setDisabledIcon(IconLoader.getDisabledIcon(icon));
       }
     }
   }
 }
 private void updateIcon(AnAction action) {
   if (isToggleable()
       && (myPresentation.getIcon() == null
           || myInsideCheckedGroup
           || !UISettings.getInstance().SHOW_ICONS_IN_MENUS)) {
     action.update(myEvent);
     myToggled =
         Boolean.TRUE.equals(
             myEvent.getPresentation().getClientProperty(Toggleable.SELECTED_PROPERTY));
     if (ActionPlaces.MAIN_MENU.equals(myPlace) && SystemInfo.isMacSystemMenu
         || UIUtil.isUnderNimbusLookAndFeel()
         || UIUtil.isUnderWindowsLookAndFeel() && SystemInfo.isWin7OrNewer) {
       setState(myToggled);
     } else if (!(getUI() instanceof GtkMenuItemUI)) {
       if (myToggled) {
         setIcon(ourCheckedIcon);
         setDisabledIcon(IconLoader.getDisabledIcon(ourCheckedIcon));
       } else {
         setIcon(ourUncheckedIcon);
         setDisabledIcon(IconLoader.getDisabledIcon(ourUncheckedIcon));
       }
     }
   } else {
     if (UISettings.getInstance().SHOW_ICONS_IN_MENUS) {
       Icon icon = myPresentation.getIcon();
       if (action instanceof ToggleAction && ((ToggleAction) action).isSelected(myEvent)) {
         icon = new PoppedIcon(icon, 16, 16);
       }
       setIcon(icon);
       if (myPresentation.getDisabledIcon() != null) {
         setDisabledIcon(myPresentation.getDisabledIcon());
       } else {
         setDisabledIcon(IconLoader.getDisabledIcon(icon));
       }
     }
   }
 }
public abstract class ComboBoxAction extends AnAction implements CustomComponentAction {
  private static final Icon ARROW_ICON = AllIcons.General.ComboArrow;
  private static final Icon DISABLED_ARROW_ICON = IconLoader.getDisabledIcon(ARROW_ICON);

  private boolean mySmallVariant = true;
  private DataContext myDataContext;

  protected ComboBoxAction() {}

  public void actionPerformed(AnActionEvent e) {}

  public JComponent createCustomComponent(Presentation presentation) {
    JPanel panel = new JPanel(new GridBagLayout());
    ComboBoxButton button = createComboBoxButton(presentation);
    panel.add(
        button,
        new GridBagConstraints(
            0,
            0,
            1,
            1,
            1,
            1,
            GridBagConstraints.CENTER,
            GridBagConstraints.BOTH,
            new Insets(0, 3, 0, 3),
            0,
            0));
    return panel;
  }

  protected ComboBoxButton createComboBoxButton(Presentation presentation) {
    return new ComboBoxButton(presentation);
  }

  public boolean isSmallVariant() {
    return mySmallVariant;
  }

  public void setSmallVariant(boolean smallVariant) {
    mySmallVariant = smallVariant;
  }

  @Override
  public void update(AnActionEvent e) {
    super.update(e);
    myDataContext = e.getDataContext();
  }

  @NotNull
  protected abstract DefaultActionGroup createPopupActionGroup(JComponent button);

  protected int getMaxRows() {
    return 30;
  }

  protected int getMinHeight() {
    return 1;
  }

  protected int getMinWidth() {
    return 1;
  }

  protected class ComboBoxButton extends JButton {
    private final Presentation myPresentation;
    private boolean myForcePressed = false;
    private PropertyChangeListener myButtonSynchronizer;
    private boolean myMouseInside = false;
    private JBPopup myPopup;

    public ComboBoxButton(Presentation presentation) {
      myPresentation = presentation;
      setModel(new MyButtonModel());
      setHorizontalAlignment(LEFT);
      setFocusable(false);
      Insets margins = getMargin();
      setMargin(new Insets(margins.top, 2, margins.bottom, 2));
      if (isSmallVariant()) {
        setBorder(IdeBorderFactory.createEmptyBorder(0, 2, 0, 2));
        if (!UIUtil.isUnderGTKLookAndFeel()) {
          setFont(UIUtil.getLabelFont().deriveFont(11.0f));
        }
      }
      addActionListener(
          new ActionListener() {
            public void actionPerformed(ActionEvent e) {
              if (!myForcePressed) {
                IdeFocusManager.getGlobalInstance()
                    .doWhenFocusSettlesDown(
                        new Runnable() {
                          public void run() {
                            showPopup();
                          }
                        });
              }
            }
          });

      //noinspection HardCodedStringLiteral
      putClientProperty("Quaqua.Button.style", "placard");
      addMouseListener(
          new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
              myMouseInside = true;
              repaint();
            }

            @Override
            public void mouseExited(MouseEvent e) {
              myMouseInside = false;
              repaint();
            }

            @Override
            public void mousePressed(final MouseEvent e) {
              if (SwingUtilities.isLeftMouseButton(e)) {
                e.consume();
                doClick();
              }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
              dispatchEventToPopup(e);
            }
          });
      addMouseMotionListener(
          new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent e) {
              mouseMoved(
                  new MouseEvent(
                      e.getComponent(),
                      MouseEvent.MOUSE_MOVED,
                      e.getWhen(),
                      e.getModifiers(),
                      e.getX(),
                      e.getY(),
                      e.getClickCount(),
                      e.isPopupTrigger(),
                      e.getButton()));
            }

            @Override
            public void mouseMoved(MouseEvent e) {
              dispatchEventToPopup(e);
            }
          });
    }
    // Event forwarding. We need it if user does press-and-drag gesture for opening popup and
    // choosing item there.
    // It works in JComboBox, here we provide the same behavior
    private void dispatchEventToPopup(MouseEvent e) {
      if (myPopup != null && myPopup.isVisible()) {
        JComponent content = myPopup.getContent();
        Rectangle rectangle = content.getBounds();
        Point location = rectangle.getLocation();
        SwingUtilities.convertPointToScreen(location, content);
        Point eventPoint = e.getLocationOnScreen();
        rectangle.setLocation(location);
        if (rectangle.contains(eventPoint)) {
          MouseEvent event =
              SwingUtilities.convertMouseEvent(e.getComponent(), e, myPopup.getContent());
          Component component =
              SwingUtilities.getDeepestComponentAt(content, event.getX(), event.getY());
          if (component != null) component.dispatchEvent(event);
        }
      }
    }

    public void showPopup() {
      myForcePressed = true;
      repaint();

      Runnable onDispose =
          new Runnable() {
            public void run() {
              // give button chance to handle action listener
              UIUtil.invokeLaterIfNeeded(
                  new Runnable() {
                    public void run() {
                      myForcePressed = false;
                      myPopup = null;
                    }
                  });
              repaint();
            }
          };

      myPopup = createPopup(onDispose);
      myPopup.show(new RelativePoint(this, new Point(0, this.getHeight() - 1)));
    }

    @Nullable
    @Override
    public String getToolTipText() {
      return myForcePressed ? null : super.getToolTipText();
    }

    protected JBPopup createPopup(Runnable onDispose) {
      DefaultActionGroup group = createPopupActionGroup(this);

      DataContext context = getDataContext();
      myDataContext = null;
      final ListPopup popup =
          JBPopupFactory.getInstance()
              .createActionGroupPopup(
                  null,
                  group,
                  context,
                  JBPopupFactory.ActionSelectionAid.SPEEDSEARCH,
                  false,
                  onDispose,
                  getMaxRows());
      popup.setMinimumSize(new Dimension(getMinWidth(), getMinHeight()));
      return popup;
    }

    protected DataContext getDataContext() {
      return myDataContext == null ? DataManager.getInstance().getDataContext(this) : myDataContext;
    }

    @Override
    public void removeNotify() {
      if (myButtonSynchronizer != null) {
        myPresentation.removePropertyChangeListener(myButtonSynchronizer);
        myButtonSynchronizer = null;
      }
      super.removeNotify();
    }

    @Override
    public void addNotify() {
      super.addNotify();
      if (myButtonSynchronizer == null) {
        myButtonSynchronizer = new MyButtonSynchronizer();
        myPresentation.addPropertyChangeListener(myButtonSynchronizer);
      }
      initButton();
    }

    private void initButton() {
      setIcon(myPresentation.getIcon());
      setEnabled(myPresentation.isEnabled());
      setText(myPresentation.getText());
      updateTooltipText(myPresentation.getDescription());
      updateButtonSize();
    }

    private void updateTooltipText(String description) {
      String tooltip = AnAction.createTooltipText(description, ComboBoxAction.this);
      setToolTipText(tooltip.length() > 0 ? tooltip : null);
    }

    @Override
    public void updateUI() {
      super.updateUI();
      // putClientProperty(SwingUtilities2.AA_TEXT_PROPERTY_KEY, null);
      if (UIUtil.isMotifLookAndFeel()) {
        setBorder(BorderFactory.createEtchedBorder());
      } else if (!UIUtil.isUnderGTKLookAndFeel()) {
        setBorder(UIUtil.getButtonBorder());
      }
    }

    protected class MyButtonModel extends DefaultButtonModel {
      public boolean isPressed() {
        return myForcePressed || super.isPressed();
      }

      public boolean isArmed() {
        return myForcePressed || super.isArmed();
      }
    }

    private class MyButtonSynchronizer implements PropertyChangeListener {
      public void propertyChange(PropertyChangeEvent evt) {
        String propertyName = evt.getPropertyName();
        if (Presentation.PROP_TEXT.equals(propertyName)) {
          setText((String) evt.getNewValue());
          updateButtonSize();
        } else if (Presentation.PROP_DESCRIPTION.equals(propertyName)) {
          updateTooltipText((String) evt.getNewValue());
        } else if (Presentation.PROP_ICON.equals(propertyName)) {
          setIcon((Icon) evt.getNewValue());
          updateButtonSize();
        } else if (Presentation.PROP_ENABLED.equals(propertyName)) {
          setEnabled(((Boolean) evt.getNewValue()).booleanValue());
        }
      }
    }

    @Override
    public Insets getInsets() {
      final Insets insets = super.getInsets();
      return new Insets(
          insets.top, insets.left, insets.bottom, insets.right + ARROW_ICON.getIconWidth());
    }

    @Override
    public Insets getInsets(Insets insets) {
      final Insets result = super.getInsets(insets);

      if (UIUtil.isUnderNimbusLookAndFeel() && !isSmallVariant()) {
        result.top += 2;
        result.left += 8;
        result.bottom += 2;
        result.right += 4 + ARROW_ICON.getIconWidth();
      } else {
        result.right += ARROW_ICON.getIconWidth();
      }

      return result;
    }

    @Override
    public boolean isOpaque() {
      return !isSmallVariant();
    }

    @Override
    public Dimension getPreferredSize() {
      final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
      int width = isEmpty ? 10 + ARROW_ICON.getIconWidth() : super.getPreferredSize().width;
      if (isSmallVariant()) width += 4;
      return new Dimension(
          width, isSmallVariant() ? 19 : UIUtil.isUnderNimbusLookAndFeel() ? 24 : 21);
    }

    @Override
    public void paint(Graphics g) {
      UIUtil.paintWithRetina(
          getSize(),
          g,
          UIUtil.isUnderDarcula(),
          new Consumer<Graphics2D>() {
            @Override
            public void consume(Graphics2D graphics) {
              doPaint(graphics);
            }
          });
    }

    private void doPaint(Graphics g) {
      GraphicsUtil.setupAntialiasing(g);

      final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
      final Dimension size = getSize();
      if (isSmallVariant()) {
        final Graphics2D g2 = (Graphics2D) g;
        g2.setColor(UIUtil.getControlColor());
        final int w = getWidth();
        final int h = getHeight();
        if (getModel().isArmed() && getModel().isPressed()) {
          g2.setPaint(
              new GradientPaint(
                  0,
                  0,
                  UIUtil.getControlColor(),
                  0,
                  h,
                  ColorUtil.shift(UIUtil.getControlColor(), 0.8)));
        } else {
          g2.setPaint(
              new GradientPaint(
                  0,
                  0,
                  ColorUtil.shift(UIUtil.getControlColor(), 1.1),
                  0,
                  h,
                  ColorUtil.shift(UIUtil.getControlColor(), 0.9)));
        }
        g2.fillRect(2, 0, w - 2, h);
        GraphicsUtil.setupAntialiasing(g2);
        if (!myMouseInside) {
          g2.setPaint(
              new GradientPaint(
                  0, 0, UIUtil.getBorderColor(), 0, h, UIUtil.getBorderColor().darker()));
          // g2.setColor(UIUtil.getBorderColor());
        } else {
          g2.setPaint(
              new GradientPaint(
                  0,
                  0,
                  UIUtil.getBorderColor().darker(),
                  0,
                  h,
                  UIUtil.getBorderColor().darker().darker()));
        }
        g2.drawRect(2, 0, w - 3, h - 1);
        final Icon icon = getIcon();
        int x = 7;
        if (icon != null) {
          icon.paintIcon(null, g, x, (size.height - icon.getIconHeight()) / 2);
          x += icon.getIconWidth() + 3;
        }
        if (!StringUtil.isEmpty(getText())) {
          final Font font = getFont();
          g2.setFont(font);
          g2.setColor(UIManager.getColor("Panel.foreground"));
          g2.drawString(getText(), x, (size.height + font.getSize()) / 2 - 1);
        }
      } else {
        super.paintComponent(g);
      }
      final Insets insets = super.getInsets();
      final Icon icon = isEnabled() ? ARROW_ICON : DISABLED_ARROW_ICON;
      final int x;
      if (isEmpty) {
        x = (size.width - icon.getIconWidth()) / 2;
      } else {
        if (isSmallVariant()) {
          x = size.width - icon.getIconWidth() - insets.right + 1;
        } else {
          x =
              size.width
                  - icon.getIconWidth()
                  - insets.right
                  + (UIUtil.isUnderNimbusLookAndFeel() ? -3 : 2);
        }
      }
      if (UIUtil.isUnderDarcula()) {
        g.setXORMode(new Color(208, 188, 159));
      }
      icon.paintIcon(null, g, x, (size.height - icon.getIconHeight()) / 2);
      g.setPaintMode();
    }

    protected void updateButtonSize() {
      invalidate();
      repaint();
    }
  }
}
/** @author Eugene Zhuravlev Date: 9/18/12 */
public class ProblemsViewImpl extends ProblemsView {
  private static final String PROBLEMS_TOOLWINDOW_ID = "Problems";

  private final ProblemsViewPanel myPanel;
  private final SequentialTaskExecutor myViewUpdater =
      new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
  private final Icon myActiveIcon = AllIcons.Toolwindows.Problems;
  private final Icon myPassiveIcon = IconLoader.getDisabledIcon(myActiveIcon);

  public ProblemsViewImpl(final Project project, final ToolWindowManager wm) {
    super(project);
    myPanel = new ProblemsViewPanel(project);
    Disposer.register(
        project,
        new Disposable() {
          @Override
          public void dispose() {
            Disposer.dispose(myPanel);
          }
        });
    UIUtil.invokeLaterIfNeeded(
        new Runnable() {
          @Override
          public void run() {
            if (project.isDisposed()) {
              return;
            }
            final ToolWindow tw =
                wm.registerToolWindow(
                    PROBLEMS_TOOLWINDOW_ID, false, ToolWindowAnchor.BOTTOM, project, true);
            updateIcon(false);
            final Content content =
                ContentFactory.SERVICE.getInstance().createContent(myPanel, "", false);
            // todo: setup content?
            tw.getContentManager().addContent(content);
            Disposer.register(
                project,
                new Disposable() {
                  @Override
                  public void dispose() {
                    tw.getContentManager().removeAllContents(true);
                  }
                });
          }
        });
  }

  @Override
  public void clearOldMessages(
      @Nullable final CompileScope scope, @NotNull final UUID currentSessionId) {
    myViewUpdater.execute(
        new Runnable() {
          @Override
          public void run() {
            updateIcon(
                !cleanupChildrenRecursively(
                    myPanel.getErrorViewStructure().getRootElement(), scope, currentSessionId));
            myPanel.reload();
          }
        });
  }

  private boolean cleanupChildrenRecursively(
      @NotNull final Object fromElement,
      final @Nullable CompileScope scope,
      @NotNull UUID currentSessionId) {
    final ErrorViewStructure structure = myPanel.getErrorViewStructure();
    ErrorTreeElement[] elements = structure.getChildElements(fromElement);
    if (elements.length == 0) return true;

    boolean result = false;
    for (ErrorTreeElement element : elements) {
      if (element instanceof GroupingElement) {
        if (scope != null) {
          final VirtualFile file = ((GroupingElement) element).getFile();
          if (file != null && !scope.belongs(file.getUrl())) {
            continue;
          }
        }
        if (!currentSessionId.equals(element.getData())) {
          structure.removeElement(element);
          result = true;
        } else {
          result |= cleanupChildrenRecursively(element, scope, currentSessionId);
        }
      } else {
        if (!currentSessionId.equals(element.getData())) {
          structure.removeElement(element);
          result = true;
        }
      }
    }
    return result;
  }

  @Override
  public void addMessage(
      final int type,
      @NotNull final String[] text,
      @Nullable final String groupName,
      @Nullable final Navigatable navigatable,
      @Nullable final String exportTextPrefix,
      @Nullable final String rendererTextPrefix,
      @Nullable final UUID sessionId) {

    myViewUpdater.execute(
        new Runnable() {
          @Override
          public void run() {
            final ErrorViewStructure structure = myPanel.getErrorViewStructure();
            final GroupingElement group = structure.lookupGroupingElement(groupName);
            if (group != null && !sessionId.equals(group.getData())) {
              structure.removeElement(group);
            }
            if (navigatable != null) {
              myPanel.addMessage(
                  type,
                  text,
                  groupName,
                  navigatable,
                  exportTextPrefix,
                  rendererTextPrefix,
                  sessionId);
            } else {
              myPanel.addMessage(type, text, null, -1, -1, sessionId);
            }
            updateIcon(true);
          }
        });
  }

  private void updateIcon(final boolean active) {
    ApplicationManager.getApplication()
        .invokeLater(
            new Runnable() {
              @Override
              public void run() {
                final ToolWindowManager twManager = ToolWindowManager.getInstance(myProject);
                final ToolWindow tw = twManager.getToolWindow(PROBLEMS_TOOLWINDOW_ID);
                tw.setIcon(active ? myActiveIcon : myPassiveIcon);
              }
            },
            myProject.getDisposed());
  }

  @Override
  public void setProgress(String text, float fraction) {
    myPanel.setProgress(text, fraction);
  }

  @Override
  public void setProgress(String text) {
    myPanel.setProgressText(text);
  }

  @Override
  public void clearProgress() {
    myPanel.clearProgressData();
  }
}