@Override
  protected void paintIcon(JComponent c, Graphics2D g, Rectangle viewRect, Rectangle iconRect) {
    int rad = JBUI.scale(4);

    // Paint the radio button
    final int x = iconRect.x + (rad - (rad % 2 == 1 ? 1 : 0)) / 2;
    final int y = iconRect.y + (rad - (rad % 2 == 1 ? 1 : 0)) / 2;
    final int w = iconRect.width - rad;
    final int h = iconRect.height - rad;
    final boolean enabled = c.isEnabled();
    Color color = enabled ? Gray.x50 : Gray.xD3;
    g.translate(x, y);
    // setup AA for lines
    final GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
    g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
    final boolean selected = ((AbstractButton) c).isSelected();
    g.setPaint(color);
    g.drawOval(0, 0, w, h);

    if (selected) {
      g.setColor(color);
      g.fillOval(JBUI.scale(3), JBUI.scale(3), w - 2 * JBUI.scale(3), h - 2 * JBUI.scale(3));
    }
    config.restore();
    g.translate(-x, -y);
  }
  @Override
  public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
    final Graphics2D g2d = (Graphics2D) g;
    final Insets ins = getBorderInsets(c);
    final int yOff = (ins.top + ins.bottom) / 4;
    final boolean square = DarculaButtonUI.isSquare(c);
    int offset = JBUI.scale(square ? 1 : getOffset());
    if (c.hasFocus()) {
      DarculaUIUtil.paintFocusRing(g2d, offset, yOff, width - 2 * offset, height - 2 * yOff);
    } else {
      final GraphicsConfig config = new GraphicsConfig(g);
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
      g2d.setPaint(
          UIUtil.getGradientPaint(
              width / 2,
              y + yOff + 1,
              Gray._80.withAlpha(90),
              width / 2,
              height - 2 * yOff,
              Gray._90.withAlpha(90)));
      // g.drawRoundRect(x + offset + 1, y + yOff + 1, width - 2 * offset, height - 2*yOff, 5, 5);

      ((Graphics2D) g).setPaint(Gray._100.withAlpha(180));
      g.drawRoundRect(
          x + offset,
          y + yOff,
          width - 2 * offset,
          height - 2 * yOff,
          JBUI.scale(square ? 3 : 5),
          JBUI.scale(square ? 3 : 5));

      config.restore();
    }
  }
    private JComponent createLogo() {
      NonOpaquePanel panel = new NonOpaquePanel(new BorderLayout());
      ApplicationInfoEx app = ApplicationInfoEx.getInstanceEx();
      JLabel logo = new JLabel(IconLoader.getIcon(app.getWelcomeScreenLogoUrl()));
      logo.setBorder(JBUI.Borders.empty(30, 0, 10, 0));
      logo.setHorizontalAlignment(SwingConstants.CENTER);
      panel.add(logo, BorderLayout.NORTH);
      JLabel appName = new JLabel(ApplicationNamesInfo.getInstance().getFullProductName());
      Font font = getProductFont();
      appName.setForeground(JBColor.foreground());
      appName.setFont(font.deriveFont(JBUI.scale(36f)).deriveFont(Font.PLAIN));
      appName.setHorizontalAlignment(SwingConstants.CENTER);
      String appVersion = "Version " + app.getFullVersion();

      if (app.isEAP() && app.getBuild().getBuildNumber() < Integer.MAX_VALUE) {
        appVersion += " (" + app.getBuild().asString() + ")";
      }

      JLabel version = new JLabel(appVersion);
      version.setFont(getProductFont().deriveFont(JBUI.scale(16f)));
      version.setHorizontalAlignment(SwingConstants.CENTER);
      version.setForeground(Gray._128);

      panel.add(appName);
      panel.add(version, BorderLayout.SOUTH);
      panel.setBorder(JBUI.Borders.emptyBottom(20));
      return panel;
    }
    private JComponent createActionPanel() {
      JPanel actions = new NonOpaquePanel();
      actions.setBorder(JBUI.Borders.emptyLeft(10));
      actions.setLayout(new BoxLayout(actions, BoxLayout.Y_AXIS));
      ActionManager actionManager = ActionManager.getInstance();
      ActionGroup quickStart =
          (ActionGroup) actionManager.getAction(IdeActions.GROUP_WELCOME_SCREEN_QUICKSTART);
      DefaultActionGroup group = new DefaultActionGroup();
      collectAllActions(group, quickStart);

      for (AnAction action : group.getChildren(null)) {
        JPanel button = new JPanel(new BorderLayout());
        button.setOpaque(false);
        button.setBorder(JBUI.Borders.empty(8, 20));
        AnActionEvent e =
            AnActionEvent.createFromAnAction(
                action,
                null,
                ActionPlaces.WELCOME_SCREEN,
                DataManager.getInstance().getDataContext(this));
        action.update(e);
        Presentation presentation = e.getPresentation();
        if (presentation.isVisible()) {
          String text = presentation.getText();
          if (text != null && text.endsWith("...")) {
            text = text.substring(0, text.length() - 3);
          }
          Icon icon = presentation.getIcon();
          if (icon.getIconHeight() != JBUI.scale(16) || icon.getIconWidth() != JBUI.scale(16)) {
            icon = JBUI.emptyIcon(16);
          }
          action = wrapGroups(action);
          ActionLink link = new ActionLink(text, icon, action, createUsageTracker(action));
          link.setPaintUnderline(false);
          link.setNormalColor(getLinkNormalColor());
          button.add(link);
          if (action instanceof WelcomePopupAction) {
            button.add(createArrow(link), BorderLayout.EAST);
          }
          installFocusable(button, action, KeyEvent.VK_UP, KeyEvent.VK_DOWN, true);
          actions.add(button);
        }
      }

      WelcomeScreenActionsPanel panel = new WelcomeScreenActionsPanel();
      panel.actions.add(actions);
      return panel.root;
    }
  private static void patchHiDPI(UIDefaults defaults) {
    if (!JBUI.isHiDPI()) return;

    List<String> myIntKeys = Arrays.asList("Tree.leftChildIndent", "Tree.rightChildIndent");
    List<String> patched = new ArrayList<String>();
    for (Map.Entry<Object, Object> entry : defaults.entrySet()) {
      Object value = entry.getValue();
      String key = entry.getKey().toString();
      if (value instanceof DimensionUIResource) {
        entry.setValue(JBUI.size((DimensionUIResource) value).asUIResource());
      } else if (value instanceof InsetsUIResource) {
        entry.setValue(JBUI.insets(((InsetsUIResource) value)).asUIResource());
      } else if (value instanceof Integer) {
        if (key.endsWith(".maxGutterIconWidth") || myIntKeys.contains(key)) {
          if (!"true".equals(defaults.get(key + ".hidpi.patched"))) {
            entry.setValue(Integer.valueOf(JBUI.scale((Integer) value)));
            patched.add(key);
          }
        }
      }
    }
    for (String key : patched) {
      defaults.put(key + ".hidpi.patched", "true");
    }
  }
  ShortcutFilteringPanel() {
    super(new VerticalLayout(JBUI.scale(2)));

    myKeyboardPanel.myFirstStroke.setColumns(13);
    myKeyboardPanel.myFirstStroke.putClientProperty("JTextField.variant", "search");
    myKeyboardPanel.mySecondStroke.setColumns(13);
    myKeyboardPanel.mySecondStroke.putClientProperty("JTextField.variant", "search");
    myKeyboardPanel.mySecondStroke.setVisible(false);
    myKeyboardPanel.mySecondStrokeEnable.setText(
        KeyMapBundle.message("filter.enable.second.stroke.checkbox"));
    myKeyboardPanel.mySecondStrokeEnable.addChangeListener(myChangeListener);
    myKeyboardPanel.add(VerticalLayout.TOP, myKeyboardPanel.myFirstStroke);
    myKeyboardPanel.add(VerticalLayout.TOP, myKeyboardPanel.mySecondStrokeEnable);
    myKeyboardPanel.add(VerticalLayout.TOP, myKeyboardPanel.mySecondStroke);
    myKeyboardPanel.addPropertyChangeListener("shortcut", myPropertyListener);
    myKeyboardPanel.setBorder(JBUI.Borders.empty(4));

    JLabel label = new JLabel(KeyMapBundle.message("filter.mouse.pad.label"));
    label.setOpaque(false);
    label.setIcon(AllIcons.General.MouseShortcut);
    label.setForeground(MouseShortcutPanel.FOREGROUND);
    label.setBorder(JBUI.Borders.empty(14, 4));
    myMousePanel.add(BorderLayout.CENTER, label);
    myMousePanel.addPropertyChangeListener("shortcut", myPropertyListener);
    myMousePanel.setBorder(JBUI.Borders.customLine(MouseShortcutPanel.BORDER, 1, 0, 0, 0));

    add(VerticalLayout.TOP, myKeyboardPanel);
    add(VerticalLayout.TOP, myMousePanel);
    addPropertyChangeListener("shortcut", myPropertyListener);
  }
 private static void readFontSettings(
     @NotNull Element element, @NotNull FontPreferences preferences, boolean isDefaultScheme) {
   List children = element.getChildren(OPTION_ELEMENT);
   String fontFamily = null;
   int size = -1;
   for (Object child : children) {
     Element e = (Element) child;
     if (EDITOR_FONT_NAME.equals(e.getAttributeValue(NAME_ATTR))) {
       fontFamily = getValue(e);
     } else if (EDITOR_FONT_SIZE.equals(e.getAttributeValue(NAME_ATTR))) {
       try {
         size = Integer.parseInt(getValue(e));
         if (isDefaultScheme) {
           size = JBUI.scale(size);
         }
       } catch (NumberFormatException ex) {
         // ignore
       }
     }
   }
   if (fontFamily != null && size > 1) {
     preferences.register(fontFamily, size);
   } else if (fontFamily != null) {
     preferences.addFontFamily(fontFamily);
   }
 }
 private void setFixedColumnWidth(final int columnIndex, String sampleText) {
   final TableColumn column =
       myEntryTable.getTableHeader().getColumnModel().getColumn(columnIndex);
   final FontMetrics fontMetrics = myEntryTable.getFontMetrics(myEntryTable.getFont());
   final int width = fontMetrics.stringWidth(" " + sampleText + " ") + JBUI.scale(4);
   column.setPreferredWidth(width);
   column.setMinWidth(width);
   column.setResizable(false);
 }
Exemple #9
0
    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);

      int count = getComponentCount() - 1;
      if (count > 0) {
        int x2 = getWidth() - JBUI.scale(16);
        int y = 0;

        g.setColor(new JBColor(0xD0D0D0, 0x717375));

        for (int i = 0; i < count; i++) {
          Dimension size = getComponent(i).getPreferredSize();
          y += size.height + 1;
          g.drawLine(JBUI.scale(16), y, x2, y);
        }
      }
    }
  private void paintCaret(Graphics2D g_) {
    EditorImpl.CaretRectangle[] locations = myEditor.getCaretLocations(true);
    if (locations == null) return;

    Graphics2D g = IdeBackgroundUtil.getOriginalGraphics(g_);
    int lineHeight = myView.getLineHeight();
    EditorSettings settings = myEditor.getSettings();
    Color caretColor = myEditor.getColorsScheme().getColor(EditorColors.CARET_COLOR);
    if (caretColor == null) caretColor = new JBColor(CARET_DARK, CARET_LIGHT);
    g.setColor(caretColor);
    for (EditorImpl.CaretRectangle location : locations) {
      int x = location.myPoint.x;
      int y = location.myPoint.y;
      Caret caret = location.myCaret;
      boolean isRtl = location.myIsRtl;
      if (myEditor.isInsertMode() != settings.isBlockCursor()) {
        int lineWidth = JBUI.scale(settings.getLineCursorWidth());
        g.fillRect(x, y, lineWidth, lineHeight);
        if (myDocument.getTextLength() > 0
            && caret != null
            && !myView.getLineLayout(caret.getLogicalPosition().line).isLtr()) {
          g.fillPolygon(
              new int[] {
                isRtl ? x + lineWidth : x,
                isRtl ? x + lineWidth - CARET_DIRECTION_MARK_SIZE : x + CARET_DIRECTION_MARK_SIZE,
                isRtl ? x + lineWidth : x
              },
              new int[] {y, y, y + CARET_DIRECTION_MARK_SIZE},
              3);
        }
      } else {
        int width = location.myWidth;
        int startX = Math.max(0, isRtl ? x - width : x);
        g.fillRect(startX, y, width, lineHeight - 1);
        if (myDocument.getTextLength() > 0 && caret != null) {
          int targetVisualColumn = caret.getVisualPosition().column;
          for (VisualLineFragmentsIterator.Fragment fragment :
              VisualLineFragmentsIterator.create(myView, caret.getVisualLineStart(), false)) {
            int startVisualColumn = fragment.getStartVisualColumn();
            int endVisualColumn = fragment.getEndVisualColumn();
            if (startVisualColumn < targetVisualColumn && endVisualColumn > targetVisualColumn
                || startVisualColumn == targetVisualColumn && !isRtl
                || endVisualColumn == targetVisualColumn && isRtl) {
              g.setColor(ColorUtil.isDark(caretColor) ? CARET_LIGHT : CARET_DARK);
              fragment.draw(
                  g,
                  startX,
                  y + myView.getAscent(),
                  targetVisualColumn - startVisualColumn - (isRtl ? 1 : 0),
                  targetVisualColumn - startVisualColumn + (isRtl ? 0 : 1));
              break;
            }
          }
        }
      }
    }
  }
 private void readSettings(Element childNode) {
   String name = childNode.getAttributeValue(NAME_ATTR);
   String value = getValue(childNode);
   if (LINE_SPACING.equals(name)) {
     myLineSpacing = Float.parseFloat(value);
   } else if (EDITOR_FONT_SIZE.equals(name)) {
     setEditorFontSize(JBUI.scale(Integer.parseInt(value)));
   } else if (EDITOR_FONT_NAME.equals(name)) {
     setEditorFontName(value);
   } else if (CONSOLE_LINE_SPACING.equals(name)) {
     setConsoleLineSpacing(Float.parseFloat(value));
   } else if (CONSOLE_FONT_SIZE.equals(name)) {
     setConsoleFontSize(JBUI.scale(Integer.parseInt(value)));
   } else if (CONSOLE_FONT_NAME.equals(name)) {
     setConsoleFontName(value);
   } else if (EDITOR_QUICK_JAVADOC_FONT_SIZE.equals(name)) {
     myQuickDocFontSize = FontSize.valueOf(value);
   }
 }
 @Nullable
 public static Image loadFromResource(@NonNls @NotNull String path, @NotNull Class aClass) {
   return ImageDescList.create(
           path,
           aClass,
           UIUtil.isUnderDarcula(),
           UIUtil.isRetina() || JBUI.scale(1.0f) >= 1.5f,
           true)
       .load(ImageConverterChain.create().withRetina());
 }
    private int computeHeight() {
      FontMetrics fm = myRootPane.getFontMetrics(getFont());
      int fontHeight = fm.getHeight();
      fontHeight += 7;
      int iconHeight = 0;
      if (getWindowDecorationStyle() == JRootPane.FRAME) {
        iconHeight = IMAGE_HEIGHT;
      }

      return Math.max(Math.max(fontHeight, iconHeight), JBUI.scale(myIdeMenu == null ? 28 : 36));
    }
  @Override
  protected void paintCheckSign(Graphics2D g, boolean enabled, int w, int h) {
    g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
    g.setStroke(
        new BasicStroke(JBUI.scale(1) * 2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

    g.setPaint(getShadowColor(enabled, true));
    final int x1 = JBUI.scale(5);
    final int y1 = JBUI.scale(9);
    final int x2 = JBUI.scale(7);
    final int y2 = JBUI.scale(11);
    g.drawLine(x1, y1, x2, y2);
    g.drawLine(x2, y2, w - JBUI.scale(2) - 1, JBUI.scale(5));
    g.setPaint(getCheckSignColor(enabled, true));
    g.drawLine(x1, y1 - 2, x2, y2 - 2);
    g.drawLine(x2, y2 - 2, w - JBUI.scale(2) - 1, JBUI.scale(5) - 2);
  }
 public SimpleColoredComponent() {
   myFragments = new ArrayList<>(3);
   myLayouts = new ArrayList<>(3);
   myAttributes = new ArrayList<>(3);
   myIpad = new JBInsets(1, 2, 1, 2);
   myIconTextGap = JBUI.scale(2);
   myBorder = new MyBorder();
   myFragmentPadding = new TIntIntHashMap(10);
   myFragmentAlignment = new TIntIntHashMap(10);
   setOpaque(true);
   updateUI();
 }
 @Override
 public void setUI(ProgressBarUI ui) {
   boolean nativeLaf =
       UIUtil.isUnderWindowsLookAndFeel()
           || UIUtil.isUnderAquaLookAndFeel()
           || UIUtil.isUnderGTKLookAndFeel();
   if (nativeLaf) {
     ui = new DarculaProgressBarUI();
   }
   super.setUI(ui);
   if (nativeLaf) {
     setPreferredSize(new Dimension(getPreferredSize().width, JBUI.scale(NATIVE_LAF_HEIGHT)));
   }
 }
 private void syncFontFamilies() {
   if (myIsInSchemeChange) {
     return;
   }
   FontPreferences fontPreferences = getFontPreferences();
   fontPreferences.clearFonts();
   String primaryFontFamily = myPrimaryCombo.getFontName();
   String secondaryFontFamily =
       mySecondaryCombo.isEnabled() ? mySecondaryCombo.getFontName() : null;
   int fontSize = getFontSizeFromField();
   if (primaryFontFamily != null) {
     if (!FontPreferences.DEFAULT_FONT_NAME.equals(primaryFontFamily)) {
       fontPreferences.addFontFamily(primaryFontFamily);
     }
     fontPreferences.register(primaryFontFamily, JBUI.scale(fontSize));
   }
   if (secondaryFontFamily != null) {
     if (!FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)) {
       fontPreferences.addFontFamily(secondaryFontFamily);
     }
     fontPreferences.register(secondaryFontFamily, JBUI.scale(fontSize));
   }
   updateDescription(true);
 }
  @NotNull
  public final synchronized Dimension computePreferredSize(final boolean mainTextOnly) {
    // Calculate width
    int width = myIpad.left;

    if (myIcon != null) {
      width += myIcon.getIconWidth() + myIconTextGap;
    }

    final Insets borderInsets =
        myBorder != null ? myBorder.getBorderInsets(this) : JBUI.emptyInsets();
    width += borderInsets.left;

    Font font = getBaseFont();
    LOG.assertTrue(font != null);

    width += computeTextWidth(font, mainTextOnly);
    width += myIpad.right + borderInsets.right;

    // Calculate height
    int height = myIpad.top + myIpad.bottom;

    final FontMetrics metrics = getFontMetrics(font);
    int textHeight = Math.max(JBUI.scale(16), metrics.getHeight()); // avoid too narrow rows
    textHeight += borderInsets.top + borderInsets.bottom;

    if (myIcon != null) {
      height += Math.max(myIcon.getIconHeight(), textHeight);
    } else {
      height += textHeight;
    }

    // Take into account that the component itself can have a border
    final Insets insets = getInsets();
    if (insets != null) {
      width += insets.left + insets.right;
      height += insets.top + insets.bottom;
    }

    return new Dimension(width, height);
  }
 private static void attachColorIcon(
     final PsiElement element, AnnotationHolder holder, String attributeValueText) {
   try {
     Color color = null;
     if (attributeValueText.startsWith("#")) {
       color = ColorUtil.fromHex(attributeValueText.substring(1));
     } else {
       final String hexCode =
           ColorMap.getHexCodeForColorName(StringUtil.toLowerCase(attributeValueText));
       if (hexCode != null) {
         color = ColorUtil.fromHex(hexCode);
       }
     }
     if (color != null) {
       final ColorIcon icon = JBUI.scale(new ColorIcon(8, color));
       final Annotation annotation = holder.createInfoAnnotation(element, null);
       annotation.setGutterIconRenderer(new ColorIconRenderer(icon, element));
     }
   } catch (Exception ignored) {
   }
 }
  @Override
  public void paint(Graphics2D g, int x, int y, int width, int height, Integer object) {
    g = (Graphics2D) g.create(x, y, width, height);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
    g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f));
    g.setStroke(BASIC_STROKE);

    boolean dark = UIUtil.isUnderDarcula();
    int offset = object != null ? object + 11 : 11;
    Color start = getColor(dark ? 95 + offset : 251 - offset);
    Color stop = getColor(dark ? 80 + offset : 215 - offset);

    Paint paint;
    if (Adjustable.VERTICAL == myScrollBar.getOrientation()) {
      x = 2;
      y = 1;
      width -= 3;
      height -= 2;
      if (myPainter instanceof ExtraErrorStripePainter) {
        ExtraErrorStripePainter extra = (ExtraErrorStripePainter) myPainter;
        int gap = extra.getMinimalThickness() - 1;
        x += gap;
        width -= gap;
      }
      paint = UIUtil.getGradientPaint(x, 0, start, x + width, 0, stop);
    } else {
      x = 1;
      y = 2;
      width -= 2;
      height -= 3;
      paint = UIUtil.getGradientPaint(0, y, start, 0, y + height, stop);
    }
    int arc = JBUI.scale(3);
    g.setPaint(paint);
    g.fillRoundRect(x + 1, y + 1, width - 2, height - 2, arc, arc);
    g.setColor(getColor(dark ? 85 : 201));
    g.drawRoundRect(x, y, width - 1, height - 1, arc, arc);
    g.dispose();
  }
/**
 * All icons.
 *
 * @author Yann C&eacute;bron
 */
public final class StrutsIcons {
  /** Icon for struts.xml files. */
  public static final LayeredIcon STRUTS_CONFIG_FILE = new LayeredIcon(2);

  /** Icon for validation.xml files. */
  public static final LayeredIcon VALIDATION_CONFIG_FILE = new LayeredIcon(2);

  public static final LayeredIcon ACTION_CLASS = new LayeredIcon(2);

  public static final LayeredIcon STRUTS_VARIABLE = new LayeredIcon(2);

  public static final LayeredIcon STRUTS_PACKAGE = new LayeredIcon(2);

  /** Vertical offset for small overlay icons. */
  static final int OVERLAY_Y_OFFSET = JBUI.scale(7);

  /** Horizontal offset for small overlay icons. */
  static final int OVERLAY_X_OFFSET = JBUI.scale(8);

  private StrutsIcons() {}

  /** Overlay icon for "default" elements. */
  private static final Icon OVERLAY_DEFAULT = AllIcons.Actions.Checked;

  public static final LayeredIcon RESULT_TYPE_DEFAULT = new LayeredIcon(2);

  public static final LayeredIcon GLOBAL_RESULT = new LayeredIcon(2);
  public static final LayeredIcon GLOBAL_EXCEPTION_MAPPING = new LayeredIcon(2);

  public static final LayeredIcon DEFAULT_ACTION_REF = new LayeredIcon(2);
  public static final LayeredIcon DEFAULT_CLASS_REF = new LayeredIcon(2);
  public static final LayeredIcon DEFAULT_INTERCEPTOR_REF = new LayeredIcon(2);

  // generic reference providers
  public static final Icon THEME = AllIcons.Gutter.Colors;

  static {
    STRUTS_CONFIG_FILE.setIcon(StdFileTypes.XML.getIcon(), 0);
    STRUTS_CONFIG_FILE.setIcon(Struts2Icons.Action_small, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);

    VALIDATION_CONFIG_FILE.setIcon(StdFileTypes.XML.getIcon(), 0);
    VALIDATION_CONFIG_FILE.setIcon(Struts2Icons.Edit_small, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);

    ACTION_CLASS.setIcon(AllIcons.Nodes.Class, 0);
    ACTION_CLASS.setIcon(Struts2Icons.Action_small, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);

    STRUTS_VARIABLE.setIcon(AllIcons.Nodes.Variable, 0);
    STRUTS_VARIABLE.setIcon(Struts2Icons.Action_small, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);

    STRUTS_PACKAGE.setIcon(AllIcons.Nodes.Folder, 0);
    STRUTS_PACKAGE.setIcon(Struts2Icons.Action_small, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);

    createGlobalIcon(GLOBAL_RESULT, AllIcons.Vcs.Arrow_right);
    createGlobalIcon(GLOBAL_EXCEPTION_MAPPING, AllIcons.Nodes.ExceptionClass);

    createDefaultIcon(DEFAULT_ACTION_REF, Struts2Icons.Action);
    createDefaultIcon(DEFAULT_CLASS_REF, AllIcons.Nodes.Class);
    createDefaultIcon(DEFAULT_INTERCEPTOR_REF, AllIcons.Nodes.Plugin);
    createDefaultIcon(RESULT_TYPE_DEFAULT, AllIcons.Debugger.Console);
  }

  private static void createGlobalIcon(final LayeredIcon icon, final Icon baseIcon) {
    icon.setIcon(baseIcon, 0);
    icon.setIcon(AllIcons.General.Web, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);
  }

  private static void createDefaultIcon(final LayeredIcon icon, final Icon baseIcon) {
    icon.setIcon(baseIcon, 0);
    icon.setIcon(OVERLAY_DEFAULT, 1, OVERLAY_X_OFFSET, OVERLAY_Y_OFFSET);
  }
}
public final class IconLoader {
  private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.IconLoader");
  public static boolean STRICT = false;
  private static boolean USE_DARK_ICONS = UIUtil.isUnderDarcula();
  private static float SCALE = JBUI.scale(1f);
  private static ImageFilter IMAGE_FILTER;

  @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
  private static final ConcurrentMap<URL, CachedImageIcon> ourIconsCache =
      ContainerUtil.newConcurrentMap(100, 0.9f, 2);

  /** This cache contains mapping between icons and disabled icons. */
  private static final Map<Icon, Icon> ourIcon2DisabledIcon = new WeakHashMap<Icon, Icon>(200);

  @NonNls
  private static final Map<String, String> ourDeprecatedIconsReplacements =
      new HashMap<String, String>();

  static {
    ourDeprecatedIconsReplacements.put(
        "/general/toolWindowDebugger.png", "AllIcons.Toolwindows.ToolWindowDebugger");
    ourDeprecatedIconsReplacements.put(
        "/general/toolWindowChanges.png", "AllIcons.Toolwindows.ToolWindowChanges");

    ourDeprecatedIconsReplacements.put(
        "/actions/showSettings.png", "AllIcons.General.ProjectSettings");
    ourDeprecatedIconsReplacements.put("/general/ideOptions.png", "AllIcons.General.Settings");
    ourDeprecatedIconsReplacements.put(
        "/general/applicationSettings.png", "AllIcons.General.Settings");
    ourDeprecatedIconsReplacements.put("/toolbarDecorator/add.png", "AllIcons.General.Add");
    ourDeprecatedIconsReplacements.put("/vcs/customizeView.png", "AllIcons.General.Settings");

    ourDeprecatedIconsReplacements.put("/vcs/refresh.png", "AllIcons.Actions.Refresh");
    ourDeprecatedIconsReplacements.put("/actions/sync.png", "AllIcons.Actions.Refresh");
    ourDeprecatedIconsReplacements.put("/actions/refreshUsages.png", "AllIcons.Actions.Rerun");

    ourDeprecatedIconsReplacements.put("/compiler/error.png", "AllIcons.General.Error");
    ourDeprecatedIconsReplacements.put(
        "/compiler/hideWarnings.png", "AllIcons.General.HideWarnings");
    ourDeprecatedIconsReplacements.put("/compiler/information.png", "AllIcons.General.Information");
    ourDeprecatedIconsReplacements.put("/compiler/warning.png", "AllIcons.General.Warning");
    ourDeprecatedIconsReplacements.put("/ide/errorSign.png", "AllIcons.General.Error");

    ourDeprecatedIconsReplacements.put("/ant/filter.png", "AllIcons.General.Filter");
    ourDeprecatedIconsReplacements.put("/inspector/useFilter.png", "AllIcons.General.Filter");

    ourDeprecatedIconsReplacements.put("/actions/showSource.png", "AllIcons.Actions.Preview");
    ourDeprecatedIconsReplacements.put(
        "/actions/consoleHistory.png", "AllIcons.General.MessageHistory");
    ourDeprecatedIconsReplacements.put(
        "/vcs/messageHistory.png", "AllIcons.General.MessageHistory");
  }

  private static final ImageIcon EMPTY_ICON =
      new ImageIcon(UIUtil.createImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)) {
        @NonNls
        public String toString() {
          return "Empty icon " + super.toString();
        }
      };

  private static boolean ourIsActivated = false;

  private IconLoader() {}

  @Deprecated
  public static Icon getIcon(@NotNull final Image image) {
    return new JBImageIcon(image);
  }

  public static void setUseDarkIcons(boolean useDarkIcons) {
    USE_DARK_ICONS = useDarkIcons;
    clearCache();
  }

  public static void setScale(float scale) {
    if (scale != SCALE) {
      SCALE = scale;
      clearCache();
    }
  }

  public static void setFilter(ImageFilter filter) {
    if (!Registry.is("color.blindness.icon.filter")) {
      filter = null;
    }
    if (IMAGE_FILTER != filter) {
      IMAGE_FILTER = filter;
      clearCache();
    }
  }

  private static void clearCache() {
    ourIconsCache.clear();
    ourIcon2DisabledIcon.clear();
  }

  // TODO[kb] support iconsets
  // public static Icon getIcon(@NotNull final String path, @NotNull final String darkVariantPath) {
  //  return new InvariantIcon(getIcon(path), getIcon(darkVariantPath));
  // }

  @NotNull
  public static Icon getIcon(@NonNls @NotNull final String path) {
    Class callerClass = ReflectionUtil.getGrandCallerClass();

    assert callerClass != null : path;
    return getIcon(path, callerClass);
  }

  @Nullable
  private static Icon getReflectiveIcon(@NotNull String path, ClassLoader classLoader) {
    try {
      @NonNls String pckg = path.startsWith("AllIcons.") ? "com.intellij.icons." : "icons.";
      Class cur =
          Class.forName(
              pckg + path.substring(0, path.lastIndexOf('.')).replace('.', '$'), true, classLoader);
      Field field = cur.getField(path.substring(path.lastIndexOf('.') + 1));

      return (Icon) field.get(null);
    } catch (Exception e) {
      return null;
    }
  }

  @Nullable
  /**
   * Might return null if icon was not found. Use only if you expected null return value, otherwise
   * see {@link IconLoader#getIcon(java.lang.String)}
   */
  public static Icon findIcon(@NonNls @NotNull String path) {
    Class callerClass = ReflectionUtil.getGrandCallerClass();
    if (callerClass == null) return null;
    return findIcon(path, callerClass);
  }

  @NotNull
  public static Icon getIcon(@NotNull String path, @NotNull final Class aClass) {
    final Icon icon = findIcon(path, aClass);
    if (icon == null) {
      LOG.error("Icon cannot be found in '" + path + "', aClass='" + aClass + "'");
    }
    return icon;
  }

  public static void activate() {
    ourIsActivated = true;
  }

  private static boolean isLoaderDisabled() {
    return !ourIsActivated;
  }

  /**
   * Might return null if icon was not found. Use only if you expected null return value, otherwise
   * see {@link IconLoader#getIcon(java.lang.String, java.lang.Class)}
   */
  @Nullable
  public static Icon findIcon(@NotNull final String path, @NotNull final Class aClass) {
    return findIcon(path, aClass, false);
  }

  @Nullable
  public static Icon findIcon(
      @NotNull String path, @NotNull final Class aClass, boolean computeNow) {
    path = undeprecate(path);
    if (isReflectivePath(path)) return getReflectiveIcon(path, aClass.getClassLoader());

    URL myURL = aClass.getResource(path);
    if (myURL == null) {
      if (STRICT) throw new RuntimeException("Can't find icon in '" + path + "' near " + aClass);
      return null;
    }
    return findIcon(myURL);
  }

  @NotNull
  private static String undeprecate(@NotNull String path) {
    String replacement = ourDeprecatedIconsReplacements.get(path);
    return replacement == null ? path : replacement;
  }

  private static boolean isReflectivePath(@NotNull String path) {
    List<String> paths = StringUtil.split(path, ".");
    return paths.size() > 1 && paths.get(0).endsWith("Icons");
  }

  @Nullable
  public static Icon findIcon(URL url) {
    return findIcon(url, true);
  }

  @Nullable
  public static Icon findIcon(URL url, boolean useCache) {
    if (url == null) {
      return null;
    }
    CachedImageIcon icon = ourIconsCache.get(url);
    if (icon == null) {
      icon = new CachedImageIcon(url);
      if (useCache) {
        icon = ConcurrencyUtil.cacheOrGet(ourIconsCache, url, icon);
      }
    }
    return icon;
  }

  @Nullable
  public static Icon findIcon(@NotNull String path, @NotNull ClassLoader classLoader) {
    path = undeprecate(path);
    if (isReflectivePath(path)) return getReflectiveIcon(path, classLoader);
    if (!StringUtil.startsWithChar(path, '/')) return null;

    final URL url = classLoader.getResource(path.substring(1));
    return findIcon(url);
  }

  @Nullable
  private static Icon checkIcon(final Image image, @NotNull URL url) {
    if (image == null
        || image.getHeight(LabelHolder.ourFakeComponent) < 1) { // image wasn't loaded or broken
      return null;
    }

    final Icon icon = getIcon(image);
    if (icon != null && !isGoodSize(icon)) {
      LOG.error("Invalid icon: " + url); // # 22481
      return EMPTY_ICON;
    }
    return icon;
  }

  public static boolean isGoodSize(@NotNull final Icon icon) {
    return icon.getIconWidth() > 0 && icon.getIconHeight() > 0;
  }

  /**
   * Gets (creates if necessary) disabled icon based on the passed one.
   *
   * @return <code>ImageIcon</code> constructed from disabled image of passed icon.
   */
  @Nullable
  public static Icon getDisabledIcon(Icon icon) {
    if (icon instanceof LazyIcon) icon = ((LazyIcon) icon).getOrComputeIcon();
    if (icon == null) return null;

    Icon disabledIcon = ourIcon2DisabledIcon.get(icon);
    if (disabledIcon == null) {
      if (!isGoodSize(icon)) {
        LOG.error(icon); // # 22481
        return EMPTY_ICON;
      }
      final int scale = UIUtil.isRetina() ? 2 : 1;
      @SuppressWarnings("UndesirableClassUsage")
      BufferedImage image =
          new BufferedImage(
              scale * icon.getIconWidth(),
              scale * icon.getIconHeight(),
              BufferedImage.TYPE_INT_ARGB);
      final Graphics2D graphics = image.createGraphics();

      graphics.setColor(UIUtil.TRANSPARENT_COLOR);
      graphics.fillRect(0, 0, icon.getIconWidth(), icon.getIconHeight());
      graphics.scale(scale, scale);
      icon.paintIcon(LabelHolder.ourFakeComponent, graphics, 0, 0);

      graphics.dispose();

      Image img = ImageUtil.filter(image, UIUtil.getGrayFilter());
      if (UIUtil.isRetina()) img = RetinaImage.createFrom(img, 2, ImageLoader.ourComponent);

      disabledIcon = new JBImageIcon(img);
      ourIcon2DisabledIcon.put(icon, disabledIcon);
    }
    return disabledIcon;
  }

  public static Icon getTransparentIcon(@NotNull final Icon icon) {
    return getTransparentIcon(icon, 0.5f);
  }

  public static Icon getTransparentIcon(@NotNull final Icon icon, final float alpha) {
    return new Icon() {
      @Override
      public int getIconHeight() {
        return icon.getIconHeight();
      }

      @Override
      public int getIconWidth() {
        return icon.getIconWidth();
      }

      @Override
      public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
        final Graphics2D g2 = (Graphics2D) g;
        final Composite saveComposite = g2.getComposite();
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        icon.paintIcon(c, g2, x, y);
        g2.setComposite(saveComposite);
      }
    };
  }

  private static final class CachedImageIcon implements ScalableIcon {
    private Object myRealIcon;
    @NotNull private final URL myUrl;
    private boolean dark;
    private float scale;
    private ImageFilter filter;
    private HashMap<Float, Icon> scaledIcons;

    public CachedImageIcon(@NotNull URL url) {
      myUrl = url;
      dark = USE_DARK_ICONS;
      scale = SCALE;
      filter = IMAGE_FILTER;
    }

    @NotNull
    private synchronized Icon getRealIcon() {
      if (isLoaderDisabled()
          && (myRealIcon == null
              || dark != USE_DARK_ICONS
              || scale != SCALE
              || filter != IMAGE_FILTER)) return EMPTY_ICON;

      if (dark != USE_DARK_ICONS || scale != SCALE || filter != IMAGE_FILTER) {
        myRealIcon = null;
        dark = USE_DARK_ICONS;
        scale = SCALE;
        filter = IMAGE_FILTER;
      }
      Object realIcon = myRealIcon;
      if (realIcon instanceof Icon) return (Icon) realIcon;

      Icon icon;
      if (realIcon instanceof Reference) {
        icon = ((Reference<Icon>) realIcon).get();
        if (icon != null) return icon;
      }

      Image image = ImageLoader.loadFromUrl(myUrl, true, filter);
      icon = checkIcon(image, myUrl);

      if (icon != null) {
        if (icon.getIconWidth() < 50 && icon.getIconHeight() < 50) {
          realIcon = icon;
        } else {
          realIcon = new SoftReference<Icon>(icon);
        }
        myRealIcon = realIcon;
      }

      return icon == null ? EMPTY_ICON : icon;
    }

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
      getRealIcon().paintIcon(c, g, x, y);
    }

    @Override
    public int getIconWidth() {
      return getRealIcon().getIconWidth();
    }

    @Override
    public int getIconHeight() {
      return getRealIcon().getIconHeight();
    }

    @Override
    public String toString() {
      return myUrl.toString();
    }

    @Override
    public Icon scale(float scaleFactor) {
      if (scaleFactor == 1f) {
        return this;
      }
      if (scaledIcons == null) {
        scaledIcons = new HashMap<Float, Icon>(1);
      }

      Icon result = scaledIcons.get(scaleFactor);
      if (result != null) {
        return result;
      }

      final Image image =
          ImageLoader.loadFromUrl(myUrl, UIUtil.isUnderDarcula(), scaleFactor >= 1.5f, filter);
      if (image != null) {
        int width = (int) (getIconWidth() * scaleFactor);
        int height = (int) (getIconHeight() * scaleFactor);
        final BufferedImage resizedImage =
            Scalr.resize(
                ImageUtil.toBufferedImage(image), Scalr.Method.ULTRA_QUALITY, width, height);
        result = getIcon(resizedImage);
        scaledIcons.put(scaleFactor, result);
        return result;
      }

      return this;
    }
  }

  public abstract static class LazyIcon implements Icon {
    private boolean myWasComputed;
    private Icon myIcon;
    private boolean isDarkVariant = USE_DARK_ICONS;
    private float scale = SCALE;
    private ImageFilter filter = IMAGE_FILTER;

    @Override
    public void paintIcon(Component c, Graphics g, int x, int y) {
      final Icon icon = getOrComputeIcon();
      if (icon != null) {
        icon.paintIcon(c, g, x, y);
      }
    }

    @Override
    public int getIconWidth() {
      final Icon icon = getOrComputeIcon();
      return icon != null ? icon.getIconWidth() : 0;
    }

    @Override
    public int getIconHeight() {
      final Icon icon = getOrComputeIcon();
      return icon != null ? icon.getIconHeight() : 0;
    }

    protected final synchronized Icon getOrComputeIcon() {
      if (!myWasComputed
          || isDarkVariant != USE_DARK_ICONS
          || scale != SCALE
          || filter != IMAGE_FILTER) {
        isDarkVariant = USE_DARK_ICONS;
        scale = SCALE;
        filter = IMAGE_FILTER;
        myWasComputed = true;
        myIcon = compute();
      }

      return myIcon;
    }

    public final void load() {
      getIconWidth();
    }

    protected abstract Icon compute();
  }

  private static class LabelHolder {
    /**
     * To get disabled icon with paint it into the image. Some icons require not null component to
     * paint.
     */
    private static final JComponent ourFakeComponent = new JLabel();
  }
}
public class RectangleReferencePainter implements ReferencePainter {
  @NotNull private List<Pair<String, Color>> myLabels = ContainerUtil.newArrayList();
  private int myHeight = JBUI.scale(22);
  private int myWidth = 0;

  private final RectanglePainter myLabelPainter =
      new RectanglePainter(false) {
        @Override
        protected Font getLabelFont() {
          return getReferenceFont();
        }
      };

  @Override
  public void customizePainter(
      @NotNull JComponent component,
      @NotNull Collection<VcsRef> references,
      @Nullable VcsLogRefManager manager,
      @NotNull Color background,
      @NotNull Color foreground) {
    FontMetrics metrics = component.getFontMetrics(getReferenceFont());
    myHeight =
        metrics.getHeight()
            + RectanglePainter.TOP_TEXT_PADDING
            + RectanglePainter.BOTTOM_TEXT_PADDING;
    myWidth = 2 * PaintParameters.LABEL_PADDING;

    myLabels = ContainerUtil.newArrayList();
    if (manager == null) return;

    List<VcsRef> sorted = ContainerUtil.sorted(references, manager.getLabelsOrderComparator());

    for (Map.Entry<VcsRefType, Collection<VcsRef>> entry :
        ContainerUtil.groupBy(sorted, VcsRef::getType).entrySet()) {
      VcsRef ref = ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(entry.getValue()));
      String text = ref.getName() + (entry.getValue().size() > 1 ? " +" : "");
      myLabels.add(Pair.create(text, entry.getKey().getBackgroundColor()));

      myWidth +=
          myLabelPainter.calculateSize(text, metrics).getWidth() + PaintParameters.LABEL_PADDING;
    }
  }

  public void paint(@NotNull Graphics2D g2, int x, int y, int height) {
    if (myLabels.isEmpty()) return;

    GraphicsConfig config = GraphicsUtil.setupAAPainting(g2);
    g2.setFont(getReferenceFont());
    g2.setStroke(new BasicStroke(1.5f));

    FontMetrics fontMetrics = g2.getFontMetrics();

    x += PaintParameters.LABEL_PADDING;
    for (Pair<String, Color> label : myLabels) {
      Dimension size = myLabelPainter.calculateSize(label.first, fontMetrics);
      int paddingY = y + (height - size.height) / 2;
      myLabelPainter.paint(g2, label.first, x, paddingY, getLabelColor(label.second));
      x += size.width + PaintParameters.LABEL_PADDING;
    }

    config.restore();
  }

  @NotNull
  public static Color getLabelColor(@NotNull Color color) {
    if (UIUtil.isUnderDarcula()) {
      color = ColorUtil.darker(color, 6);
    } else {
      color = ColorUtil.brighter(color, 6);
    }
    return ColorUtil.desaturate(color, 3);
  }

  public Dimension getSize() {
    if (myLabels.isEmpty()) return new Dimension();
    return new Dimension(myWidth, myHeight);
  }

  @Override
  public boolean isLeftAligned() {
    return true;
  }
}
/** @author Sergey.Malenkov */
final class ShortcutFilteringPanel extends JPanel {
  final KeyboardShortcutPanel myKeyboardPanel =
      new KeyboardShortcutPanel(new VerticalLayout(JBUI.scale(2)));
  final MouseShortcutPanel myMousePanel = new MouseShortcutPanel(true);

  private Shortcut myShortcut;
  private JBPopup myPopup;

  private final ChangeListener myChangeListener =
      new ChangeListener() {
        @Override
        public void stateChanged(ChangeEvent event) {
          boolean selected = myKeyboardPanel.mySecondStrokeEnable.isSelected();
          myKeyboardPanel.mySecondStroke.setVisible(selected);
          myMousePanel.setVisible(!selected);
          if (selected && myShortcut instanceof MouseShortcut) {
            setShortcut(null);
          }
        }
      };
  private final PropertyChangeListener myPropertyListener =
      new PropertyChangeListener() {
        private volatile boolean myInternal;

        @Override
        public void propertyChange(PropertyChangeEvent event) {
          boolean internal = myInternal;
          myInternal = true;
          Object value = event.getNewValue();
          if (ShortcutFilteringPanel.this == event.getSource()) {
            if (value instanceof KeyboardShortcut) {
              KeyboardShortcut shortcut = (KeyboardShortcut) value;
              myMousePanel.setShortcut(null);
              myKeyboardPanel.setShortcut(shortcut);
              if (null != shortcut.getSecondKeyStroke()) {
                myKeyboardPanel.mySecondStrokeEnable.setSelected(true);
              }
            } else {
              MouseShortcut shortcut =
                  value instanceof MouseShortcut ? (MouseShortcut) value : null;
              String text = shortcut == null ? null : KeymapUtil.getMouseShortcutText(shortcut);
              myMousePanel.setShortcut(shortcut);
              myKeyboardPanel.setShortcut(null);
              myKeyboardPanel.myFirstStroke.setText(text);
              myKeyboardPanel.mySecondStroke.setText(null);
              myKeyboardPanel.mySecondStroke.setEnabled(false);
            }
          } else if (value instanceof Shortcut) {
            setShortcut((Shortcut) value);
          } else if (!internal) {
            setShortcut(null);
          }
          myInternal = internal;
        }
      };

  ShortcutFilteringPanel() {
    super(new VerticalLayout(JBUI.scale(2)));

    myKeyboardPanel.myFirstStroke.setColumns(13);
    myKeyboardPanel.myFirstStroke.putClientProperty("JTextField.variant", "search");
    myKeyboardPanel.mySecondStroke.setColumns(13);
    myKeyboardPanel.mySecondStroke.putClientProperty("JTextField.variant", "search");
    myKeyboardPanel.mySecondStroke.setVisible(false);
    myKeyboardPanel.mySecondStrokeEnable.setText(
        KeyMapBundle.message("filter.enable.second.stroke.checkbox"));
    myKeyboardPanel.mySecondStrokeEnable.addChangeListener(myChangeListener);
    myKeyboardPanel.add(VerticalLayout.TOP, myKeyboardPanel.myFirstStroke);
    myKeyboardPanel.add(VerticalLayout.TOP, myKeyboardPanel.mySecondStrokeEnable);
    myKeyboardPanel.add(VerticalLayout.TOP, myKeyboardPanel.mySecondStroke);
    myKeyboardPanel.addPropertyChangeListener("shortcut", myPropertyListener);
    myKeyboardPanel.setBorder(JBUI.Borders.empty(4));

    JLabel label = new JLabel(KeyMapBundle.message("filter.mouse.pad.label"));
    label.setOpaque(false);
    label.setIcon(AllIcons.General.MouseShortcut);
    label.setForeground(MouseShortcutPanel.FOREGROUND);
    label.setBorder(JBUI.Borders.empty(14, 4));
    myMousePanel.add(BorderLayout.CENTER, label);
    myMousePanel.addPropertyChangeListener("shortcut", myPropertyListener);
    myMousePanel.setBorder(JBUI.Borders.customLine(MouseShortcutPanel.BORDER, 1, 0, 0, 0));

    add(VerticalLayout.TOP, myKeyboardPanel);
    add(VerticalLayout.TOP, myMousePanel);
    addPropertyChangeListener("shortcut", myPropertyListener);
  }

  Shortcut getShortcut() {
    return myShortcut;
  }

  void setShortcut(Shortcut shortcut) {
    Shortcut old = myShortcut;
    if (old != null || shortcut != null) {
      myShortcut = shortcut;
      firePropertyChange("shortcut", old, shortcut);
    }
  }

  void showPopup(Component component) {
    if (myPopup == null || myPopup.getContent() == null) {
      myPopup =
          JBPopupFactory.getInstance()
              .createComponentPopupBuilder(this, myKeyboardPanel.myFirstStroke)
              .setRequestFocus(true)
              .setTitle(KeyMapBundle.message("filter.settings.popup.title"))
              .setCancelKeyEnabled(false)
              .setMovable(true)
              .createPopup();
      IdeEventQueue.getInstance()
          .addPostprocessor(
              new IdeEventQueue.EventDispatcher() {
                boolean isEscWasPressed = false;

                @Override
                public boolean dispatch(AWTEvent e) {
                  if (e instanceof KeyEvent && e.getID() == KeyEvent.KEY_PRESSED) {
                    boolean isEsc = ((KeyEvent) e).getKeyCode() == KeyEvent.VK_ESCAPE;
                    if (isEscWasPressed && isEsc) {
                      myPopup.cancel();
                    }
                    isEscWasPressed = isEsc;
                  }
                  return false;
                }
              },
              myPopup);
    }
    myPopup.showUnderneathOf(component);
  }

  void hidePopup() {
    if (myPopup != null && myPopup.isVisible()) {
      myPopup.cancel();
    }
  }
}
Exemple #25
0
  private void addToPopup(
      @NotNull final BalloonImpl balloon, @NotNull BalloonLayoutData layoutData) {
    layoutData.doLayout =
        new Runnable() {
          @Override
          public void run() {
            WelcomeBalloonLayoutImpl.this.layoutPopup();
          }
        };
    layoutData.configuration =
        layoutData.configuration.replace(
            JBUI.scale(myPopupBalloon == null ? 7 : 5), JBUI.scale(12));

    if (myPopupBalloon == null) {
      final JScrollPane pane =
          NotificationsManagerImpl.createBalloonScrollPane(myBalloonPanel, true);
      pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
      pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);

      pane.getVerticalScrollBar()
          .addComponentListener(
              new ComponentAdapter() {
                @Override
                public void componentShown(ComponentEvent e) {
                  pane.setBorder(
                      IdeBorderFactory.createEmptyBorder(SystemInfo.isMac ? 2 : 1, 0, 1, 1));
                }

                @Override
                public void componentHidden(ComponentEvent e) {
                  pane.setBorder(IdeBorderFactory.createEmptyBorder());
                }
              });

      myPopupBalloon =
          new BalloonImpl(
              pane,
              BORDER_COLOR,
              new Insets(0, 0, 0, 0),
              FILL_COLOR,
              true,
              false,
              false,
              false,
              true,
              0,
              false,
              false,
              null,
              false,
              0,
              0,
              0,
              0,
              false,
              null,
              null,
              false,
              false,
              false,
              null,
              false);
      myPopupBalloon.setAnimationEnabled(false);
      myPopupBalloon.setShadowBorderProvider(
          new NotificationBalloonShadowBorderProvider(FILL_COLOR, BORDER_COLOR));
      myPopupBalloon.setHideListener(
          new Runnable() {
            @Override
            public void run() {
              myPopupBalloon.getComponent().setVisible(false);
            }
          });
      myPopupBalloon.setActionProvider(
          new BalloonImpl.ActionProvider() {
            private BalloonImpl.ActionButton myAction;

            @NotNull
            @Override
            public List<BalloonImpl.ActionButton> createActions() {
              myAction =
                  myPopupBalloon
                  .new ActionButton(
                      AllIcons.Ide.Notification.Close, null, null, Consumer.EMPTY_CONSUMER);
              return Collections.singletonList(myAction);
            }

            @Override
            public void layout(@NotNull Rectangle bounds) {
              myAction.setBounds(0, 0, 0, 0);
            }
          });
    }

    myBalloonPanel.add(balloon.getContent());
    balloon.getContent().putClientProperty(TYPE_KEY, layoutData.type);
    Disposer.register(
        balloon,
        new Disposable() {
          @Override
          public void dispose() {
            myBalloons.remove(balloon);
            myBalloonPanel.remove(balloon.getContent());
            updatePopup();
          }
        });
    myBalloons.add(balloon);

    updatePopup();
  }
  public void writeExternal(Element parentNode) throws WriteExternalException {
    parentNode.setAttribute(NAME_ATTR, getName());
    parentNode.setAttribute(VERSION_ATTR, Integer.toString(myVersion));

    if (myParentScheme != null) {
      parentNode.setAttribute(PARENT_SCHEME_ATTR, myParentScheme.getName());
    }

    Element element = new Element(OPTION_ELEMENT);
    element.setAttribute(NAME_ATTR, LINE_SPACING);
    element.setAttribute(VALUE_ELEMENT, String.valueOf(getLineSpacing()));
    parentNode.addContent(element);

    // IJ has used a 'single customizable font' mode for ages. That's why we want to support that
    // format now, when it's possible
    // to specify fonts sequence (see getFontPreferences()), there are big chances that many clients
    // still will use a single font.
    // That's why we want to use old format when zero or one font is selected and 'extended' format
    // otherwise.
    boolean useOldFontFormat = myFontPreferences.getEffectiveFontFamilies().size() <= 1;
    if (useOldFontFormat) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE);
      element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize() / JBUI.scale(1)));
      parentNode.addContent(element);
    } else {
      writeFontPreferences(EDITOR_FONT, parentNode, myFontPreferences);
    }

    if (!myFontPreferences.equals(myConsoleFontPreferences)) {
      if (myConsoleFontPreferences.getEffectiveFontFamilies().size() <= 1) {
        element = new Element(OPTION_ELEMENT);
        element.setAttribute(NAME_ATTR, CONSOLE_FONT_NAME);
        element.setAttribute(VALUE_ELEMENT, getConsoleFontName());
        parentNode.addContent(element);

        if (getConsoleFontSize() != getEditorFontSize()) {
          element = new Element(OPTION_ELEMENT);
          element.setAttribute(NAME_ATTR, CONSOLE_FONT_SIZE);
          element.setAttribute(
              VALUE_ELEMENT, Integer.toString(getConsoleFontSize() / JBUI.scale(1)));
          parentNode.addContent(element);
        }
      } else {
        writeFontPreferences(CONSOLE_FONT, parentNode, myConsoleFontPreferences);
      }
    }

    if (getConsoleLineSpacing() != getLineSpacing()) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, CONSOLE_LINE_SPACING);
      element.setAttribute(VALUE_ELEMENT, Float.toString(getConsoleLineSpacing()));
      parentNode.addContent(element);
    }

    if (DEFAULT_FONT_SIZE != getQuickDocFontSize()) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, EDITOR_QUICK_JAVADOC_FONT_SIZE);
      element.setAttribute(VALUE_ELEMENT, getQuickDocFontSize().toString());
      parentNode.addContent(element);
    }

    if (useOldFontFormat) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
      element.setAttribute(VALUE_ELEMENT, getEditorFontName());
      parentNode.addContent(element);
    }

    Element colorElements = new Element(COLORS_ELEMENT);
    Element attrElements = new Element(ATTRIBUTES_ELEMENT);

    writeColors(colorElements);
    writeAttributes(attrElements);

    if (colorElements.getChildren().size() > 0) {
      parentNode.addContent(colorElements);
    }
    if (attrElements.getChildren().size() > 0) {
      parentNode.addContent(attrElements);
    }
  }
  public DirDiffPanel(DirDiffTableModel model, DirDiffWindow wnd) {
    myModel = model;
    myDiffWindow = wnd;
    mySourceDirField.setText(model.getSourceDir().getPath());
    myTargetDirField.setText(model.getTargetDir().getPath());
    mySourceDirField.setBorder(JBUI.Borders.emptyRight(8));
    myTargetDirField.setBorder(JBUI.Borders.emptyRight(12));
    mySourceDirLabel.setIcon(model.getSourceDir().getIcon());
    myTargetDirLabel.setIcon(model.getTargetDir().getIcon());
    myTargetDirLabel.setBorder(JBUI.Borders.emptyLeft(8));
    myModel.setTable(myTable);
    myModel.setPanel(this);
    Disposer.register(this, myModel);
    myTable.setModel(myModel);
    new TableSpeedSearch(myTable);

    final DirDiffTableCellRenderer renderer = new DirDiffTableCellRenderer();
    myTable.setExpandableItemsEnabled(false);
    myTable.setDefaultRenderer(Object.class, renderer);
    myTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    final Project project = myModel.getProject();
    myTable
        .getSelectionModel()
        .addListSelectionListener(
            new ListSelectionListener() {
              @Override
              public void valueChanged(ListSelectionEvent e) {
                final int lastIndex = e.getLastIndex();
                final int firstIndex = e.getFirstIndex();
                final DirDiffElementImpl last = myModel.getElementAt(lastIndex);
                final DirDiffElementImpl first = myModel.getElementAt(firstIndex);
                if (last == null || first == null) {
                  update(false);
                  return;
                }
                if (last.isSeparator()) {
                  final int ind = lastIndex + ((lastIndex < firstIndex) ? 1 : -1);
                  myTable.getSelectionModel().addSelectionInterval(ind, ind);
                } else if (first.isSeparator()) {
                  final int ind = firstIndex + ((firstIndex < lastIndex) ? 1 : -1);
                  myTable.getSelectionModel().addSelectionInterval(ind, ind);
                } else {
                  update(false);
                }
                myDiffWindow.setTitle(myModel.getTitle());
              }
            });
    if (model.isOperationsEnabled()) {
      new AnAction("Change diff operation") {
        @Override
        public void actionPerformed(AnActionEvent e) {
          changeOperationForSelection();
        }
      }.registerCustomShortcutSet(CustomShortcutSet.fromString("SPACE"), myTable);
      new ClickListener() {
        @Override
        public boolean onClick(@NotNull MouseEvent e, int clickCount) {
          if (e.getButton() == MouseEvent.BUTTON3) return false;
          if (myTable.getRowCount() > 0) {
            final int row = myTable.rowAtPoint(e.getPoint());
            final int col = myTable.columnAtPoint(e.getPoint());

            if (row != -1 && col == ((myTable.getColumnCount() - 1) / 2)) {
              changeOperationForSelection();
            }
          }
          return true;
        }
      }.installOn(myTable);
    }
    myTable.addKeyListener(
        new KeyAdapter() {
          @Override
          public void keyPressed(KeyEvent e) {
            final int keyCode = e.getKeyCode();

            int row;
            if (keyCode == KeyEvent.VK_DOWN) {
              row = getNextRow();
            } else if (keyCode == KeyEvent.VK_UP) {
              row = getPrevRow();
            } else {
              row = -1;
            }

            if (row != -1) {
              selectRow(row, e.isShiftDown());
              e.consume();
            }
          }
        });
    final TableColumnModel columnModel = myTable.getColumnModel();
    final TableColumn operationColumn =
        columnModel.getColumn((columnModel.getColumnCount() - 1) / 2);
    operationColumn.setMaxWidth(JBUI.scale(25));
    operationColumn.setMinWidth(JBUI.scale(25));
    for (int i = 0; i < columnModel.getColumnCount(); i++) {
      final String name = myModel.getColumnName(i);
      final TableColumn column = columnModel.getColumn(i);
      if (DirDiffTableModel.COLUMN_DATE.equals(name)) {
        column.setMaxWidth(JBUI.scale(90));
        column.setMinWidth(JBUI.scale(90));
      } else if (DirDiffTableModel.COLUMN_SIZE.equals(name)) {
        column.setMaxWidth(JBUI.scale(120));
        column.setMinWidth(JBUI.scale(120));
      }
    }
    final DirDiffToolbarActions actions = new DirDiffToolbarActions(myModel, myDiffPanel);
    final ActionManager actionManager = ActionManager.getInstance();
    final ActionToolbar toolbar = actionManager.createActionToolbar("DirDiff", actions, true);
    registerCustomShortcuts(actions, myTable);
    myToolBarPanel.add(toolbar.getComponent(), BorderLayout.CENTER);
    final JBLabel label =
        new JBLabel(
            "Use Space button or mouse click to change operation for the selected elements."
                + " Enter to perform.",
            SwingConstants.CENTER);
    label.setForeground(UIUtil.getInactiveTextColor());
    UIUtil.applyStyle(UIUtil.ComponentStyle.MINI, label);
    DataManager.registerDataProvider(myFilesPanel, this);
    myTable.addMouseListener(
        new PopupHandler() {
          @Override
          public void invokePopup(Component comp, int x, int y) {
            final JPopupMenu popupMenu =
                actionManager
                    .createActionPopupMenu(
                        "DirDiffPanel", (ActionGroup) actionManager.getAction("DirDiffMenu"))
                    .getComponent();
            popupMenu.show(comp, x, y);
          }
        });
    myFilesPanel.add(label, BorderLayout.SOUTH);
    final JBLoadingPanel loadingPanel = new JBLoadingPanel(new BorderLayout(), wnd.getDisposable());
    loadingPanel.addListener(
        new JBLoadingPanelListener.Adapter() {
          boolean showHelp = true;

          @Override
          public void onLoadingFinish() {
            if (showHelp && myModel.isOperationsEnabled() && myModel.getRowCount() > 0) {
              final long count =
                  PropertiesComponent.getInstance().getOrInitLong("dir.diff.space.button.info", 0);
              if (count < 3) {
                JBPopupFactory.getInstance()
                    .createBalloonBuilder(new JLabel(" Use Space button to change operation"))
                    .setFadeoutTime(5000)
                    .setContentInsets(JBUI.insets(15))
                    .createBalloon()
                    .show(
                        new RelativePoint(myTable, new Point(myTable.getWidth() / 2, 0)),
                        Balloon.Position.above);
                PropertiesComponent.getInstance()
                    .setValue("dir.diff.space.button.info", String.valueOf(count + 1));
              }
            }
            showHelp = false;
          }
        });
    loadingPanel.add(myComponent, BorderLayout.CENTER);
    myTable.putClientProperty(myModel.DECORATOR, loadingPanel);
    myTable.addComponentListener(
        new ComponentAdapter() {
          @Override
          public void componentShown(ComponentEvent e) {
            myTable.removeComponentListener(this);
            myModel.reloadModel(false);
          }
        });
    myRootPanel.removeAll();
    myRootPanel.add(loadingPanel, BorderLayout.CENTER);
    myFilter =
        new FilterComponent("dir.diff.filter", 15, false) {
          @Override
          public void filter() {
            fireFilterUpdated();
          }

          @Override
          protected void onEscape(KeyEvent e) {
            e.consume();
            focusTable();
          }

          @Override
          protected JComponent getPopupLocationComponent() {
            return UIUtil.findComponentOfType(
                super.getPopupLocationComponent(), JTextComponent.class);
          }
        };

    myModel.addModelListener(
        new DirDiffModelListener() {
          @Override
          public void updateStarted() {
            myFilter.setEnabled(false);
          }

          @Override
          public void updateFinished() {
            myFilter.setEnabled(true);
          }
        });
    myFilter.getTextEditor().setColumns(10);
    myFilter.setFilter(myModel.getSettings().getFilter());
    // oldFilter = myFilter.getText();
    oldFilter = myFilter.getFilter();
    myFilterPanel.add(myFilter, BorderLayout.CENTER);
    myFilterLabel.setLabelFor(myFilter);
    final Callable<DiffElement> srcChooser = myModel.getSourceDir().getElementChooser(project);
    final Callable<DiffElement> trgChooser = myModel.getTargetDir().getElementChooser(project);
    mySourceDirField.setEditable(false);
    myTargetDirField.setEditable(false);

    if (srcChooser != null && myModel.getSettings().enableChoosers) {
      mySourceDirField.setButtonEnabled(true);
      mySourceDirField.addActionListener(
          new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
              try {
                final Callable<DiffElement> chooser =
                    myModel.getSourceDir().getElementChooser(project);
                if (chooser == null) return;
                final DiffElement newElement = chooser.call();
                if (newElement != null) {
                  if (!StringUtil.equals(mySourceDirField.getText(), newElement.getPath())) {
                    myModel.setSourceDir(newElement);
                    mySourceDirField.setText(newElement.getPath());
                    String shortcutsText =
                        KeymapUtil.getShortcutsText(
                            RefreshDirDiffAction.REFRESH_SHORTCUT.getShortcuts());
                    myModel.clearWithMessage(
                        "Source or Target has been changed."
                            + " Please run Refresh ("
                            + shortcutsText
                            + ")");
                  }
                }
              } catch (Exception ignored) {
              }
            }
          });
    } else {
      Dimension preferredSize = mySourceDirField.getPreferredSize();
      mySourceDirField.setButtonEnabled(false);
      mySourceDirField.getButton().setVisible(false);
      mySourceDirField.setPreferredSize(preferredSize);
    }

    if (trgChooser != null && myModel.getSettings().enableChoosers) {
      myTargetDirField.setButtonEnabled(true);
      myTargetDirField.addActionListener(
          new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
              try {
                final Callable<DiffElement> chooser =
                    myModel.getTargetDir().getElementChooser(project);
                if (chooser == null) return;
                final DiffElement newElement = chooser.call();
                if (newElement != null) {
                  myModel.setTargetDir(newElement);
                  myTargetDirField.setText(newElement.getPath());
                }
              } catch (Exception ignored) {
              }
            }
          });
    } else {
      Dimension preferredSize = myTargetDirField.getPreferredSize();
      myTargetDirField.setButtonEnabled(false);
      myTargetDirField.getButton().setVisible(false);
      myTargetDirField.setPreferredSize(preferredSize);
    }

    myDiffRequestProcessor = new MyDiffRequestProcessor(project);
    Disposer.register(this, myDiffRequestProcessor);
    myDiffPanel.add(myDiffRequestProcessor.getComponent(), BorderLayout.CENTER);

    myPrevNextDifferenceIterable = new MyPrevNextDifferenceIterable();
  }
 private static float calcScaleFactor(boolean allowFloatScaling) {
   float scaleFactor = allowFloatScaling ? JBUI.scale(1f) : JBUI.scale(1f) > 1.5f ? 2f : 1f;
   assert scaleFactor >= 1.0f : "By design, only scale factors >= 1.0 are supported";
   return scaleFactor;
 }
 private void paintTextEffect(
     Graphics2D g, float xFrom, float xTo, int y, Color effectColor, EffectType effectType) {
   int xStart = (int) xFrom;
   int xEnd = (int) xTo;
   g.setColor(effectColor);
   if (effectType == EffectType.LINE_UNDERSCORE) {
     UIUtil.drawLine(g, xStart, y + 1, xEnd, y + 1);
   } else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
     int height = JBUI.scale(Registry.intValue("editor.bold.underline.height", 2));
     g.fillRect(xStart, y, xEnd - xStart, height);
   } else if (effectType == EffectType.STRIKEOUT) {
     int y1 = y - myView.getCharHeight() / 2;
     UIUtil.drawLine(g, xStart, y1, xEnd, y1);
   } else if (effectType == EffectType.WAVE_UNDERSCORE) {
     UIUtil.drawWave(g, new Rectangle(xStart, y + 1, xEnd - xStart, myView.getDescent() - 1));
   } else if (effectType == EffectType.BOLD_DOTTED_LINE) {
     UIUtil.drawBoldDottedLine(
         g,
         xStart,
         xEnd,
         SystemInfo.isMac ? y : y + 1,
         myEditor.getBackgroundColor(),
         g.getColor(),
         false);
   }
 }