diff --git a/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java b/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java index 3eb3770683a6..839192003c68 100644 --- a/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java +++ b/platform/platform-api/src/com/intellij/ui/HighlightableComponent.java @@ -21,11 +21,9 @@ import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ui.UIUtil; -import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.Nullable; import javax.accessibility.Accessible; -import javax.accessibility.AccessibleAction; import javax.accessibility.AccessibleContext; import javax.accessibility.AccessibleRole; import javax.swing.*; @@ -40,7 +38,6 @@ public class HighlightableComponent extends JComponent implements Accessible { protected Icon myIcon; protected int myIconTextGap; protected ArrayList myHighlightedRegions; - protected TIntObjectHashMap myFontMetrics; protected boolean myIsSelected; protected boolean myHasFocus; protected boolean myPaintUnfocusedSelection = false; @@ -48,20 +45,13 @@ public class HighlightableComponent extends JComponent implements Accessible { public HighlightableComponent() { myIconTextGap = 4; - myFontMetrics = new TIntObjectHashMap<>(); setText(""); - fillFontMetricsMap(); setOpaque(true); + updateUI(); } - protected void fillFontMetricsMap() { - Font font = getFont(); - if (font != null){ - myFontMetrics.put(Font.PLAIN, getFontMetrics(font.deriveFont(Font.PLAIN))); - myFontMetrics.put(Font.BOLD, getFontMetrics(font.deriveFont(Font.BOLD))); - myFontMetrics.put(Font.ITALIC, getFontMetrics(font.deriveFont(Font.ITALIC))); - myFontMetrics.put(Font.BOLD | Font.ITALIC, getFontMetrics(font.deriveFont(Font.BOLD | Font.ITALIC))); - } + @Override public void updateUI() { + UISettings.setupComponentAntialiasing(this); } public void setText(String text) { @@ -88,13 +78,6 @@ public class HighlightableComponent extends JComponent implements Accessible { myIcon = icon; } - public void setFont(Font font) { - if (!font.equals(getFont())){ - super.setFont(font); - fillFontMetricsMap(); - } - } - public void addHighlighter(int startOffset, int endOffset, TextAttributes attributes) { addHighlighter(0, startOffset, endOffset, attributes); } @@ -298,7 +281,8 @@ public class HighlightableComponent extends JComponent implements Accessible { offset += defFontMetrics.stringWidth(text); } - FontMetrics fontMetrics = myFontMetrics.get(hRegion.textAttributes.getFontType()); + Font regFont = getFont().deriveFont(hRegion.textAttributes.getFontType()); + FontMetrics fontMetrics = getFontMetrics(regFont); text = myText.substring(hRegion.startOffset, hRegion.endOffset); @@ -313,8 +297,7 @@ public class HighlightableComponent extends JComponent implements Accessible { if (hRegion.textAttributes.getForegroundColor() != null && paintHighlightsForeground) { g.setColor(hRegion.textAttributes.getForegroundColor()); - } - else { + } else { g.setColor(fgColor); } @@ -323,7 +306,7 @@ public class HighlightableComponent extends JComponent implements Accessible { // draw highlight underscored line - if (hRegion.textAttributes.getEffectColor() != null) { + if (hRegion.textAttributes.getEffectType() != null && hRegion.textAttributes.getEffectColor() != null) { g.setColor(hRegion.textAttributes.getEffectColor()); int y = yOffset/*fontMetrics.getMaxAscent()*/ + 2; UIUtil.drawLine(g, offset, y, offset + fontMetrics.stringWidth(text) - 1, y); @@ -385,7 +368,9 @@ public class HighlightableComponent extends JComponent implements Accessible { if (width > x) return null; String text = getRegionText(hRegion); - FontMetrics fontMetrics = myFontMetrics.get(hRegion.textAttributes.getFontType()); + Font regFont = getFont().deriveFont(hRegion.textAttributes.getFontType()); + FontMetrics fontMetrics = getFontMetrics(regFont); + width += fontMetrics.stringWidth(text); if (width > x) return hRegion; } @@ -409,7 +394,9 @@ public class HighlightableComponent extends JComponent implements Accessible { endIndex = hRegion.endOffset; String text = getRegionText(hRegion); - FontMetrics fontMetrics = myFontMetrics.get(hRegion.textAttributes.getFontType()); + Font regFont = getFont().deriveFont(hRegion.textAttributes.getFontType()); + FontMetrics fontMetrics = getFontMetrics(regFont); + width += fontMetrics.stringWidth(text); } width += defFontMetrics.stringWidth(myText.substring(endIndex, myText.length())); diff --git a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java index b907c9955d4b..d73f5d7a6d2c 100644 --- a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java +++ b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java @@ -59,6 +59,9 @@ public class HyperlinkLabel extends HighlightableComponent { private final TextAttributes myAnchorAttributes; private HyperlinkListener myHyperlinkListener = null; + private boolean myMouseHover; + private boolean myMousePressed; + public HyperlinkLabel() { this(""); } @@ -72,8 +75,10 @@ public class HyperlinkLabel extends HighlightableComponent { } public HyperlinkLabel(String text, final Color textForegroundColor, final Color textBackgroundColor, final Color textEffectColor) { - myAnchorAttributes = + myAnchorAttributes = UIUtil.isUnderWin10LookAndFeel() ? + new Win10TextAttributes(textBackgroundColor) : new TextAttributes(textForegroundColor, textBackgroundColor, textEffectColor, EffectType.LINE_UNDERSCORE, Font.PLAIN); + enforceBackgroundOutsideText(textBackgroundColor); setHyperlinkText(text); enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK); @@ -114,11 +119,21 @@ public class HyperlinkLabel extends HighlightableComponent { } protected void processMouseEvent(MouseEvent e) { - if (e.getID() == MouseEvent.MOUSE_EXITED) { + if (e.getID() == MouseEvent.MOUSE_ENTERED && isOnLink(e.getX())) { + myMouseHover = true; + repaint(); + } else if (e.getID() == MouseEvent.MOUSE_EXITED) { setCursor(Cursor.getDefaultCursor()); - } - else if (UIUtil.isActionClick(e, MouseEvent.MOUSE_PRESSED) && isOnLink(e.getX())) { + myMouseHover = false; + myMousePressed = false; + repaint(); + } else if (UIUtil.isActionClick(e, MouseEvent.MOUSE_PRESSED) && isOnLink(e.getX())) { fireHyperlinkEvent(); + myMousePressed = true; + repaint(); + } else if (e.getID() == MouseEvent.MOUSE_RELEASED) { + myMousePressed = false; + repaint(); } super.processMouseEvent(e); } @@ -126,7 +141,14 @@ public class HyperlinkLabel extends HighlightableComponent { @Override protected void processMouseMotionEvent(MouseEvent e) { if (e.getID() == MouseEvent.MOUSE_MOVED) { - setCursor(isOnLink(e.getX()) ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) : Cursor.getDefaultCursor()); + boolean onLink = isOnLink(e.getX()); + boolean needRepaint = myMouseHover != onLink; + myMouseHover = onLink; + setCursor(myMouseHover ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) : Cursor.getDefaultCursor()); + + if (needRepaint) { + repaint(); + } } super.processMouseMotionEvent(e); } @@ -240,6 +262,7 @@ public class HyperlinkLabel extends HighlightableComponent { @Override public void updateUI() { + super.updateUI(); setFont(UIUtil.getLabelFont()); } @@ -253,7 +276,7 @@ public class HyperlinkLabel extends HighlightableComponent { /** * Hyperlink accessibility: "HYPERLINK" role and expose a "click" action. - * @see javax.swing.AbstractButton.AccessibleAbstractButton + * @see AbstractButton.AccessibleAbstractButton */ protected class AccessibleHyperlinkLabel extends AccessibleHighlightable implements AccessibleAction { @Override @@ -291,4 +314,35 @@ public class HyperlinkLabel extends HighlightableComponent { } } } + + private class Win10TextAttributes extends TextAttributes { + private Win10TextAttributes(Color textBackgroundColor) { + super(null, textBackgroundColor, null, null, Font.PLAIN); + } + + @Override public Color getForegroundColor() { + return !isEnabled() ? UIManager.getColor("Label.disabledForeground") : + myMousePressed ? UIManager.getColor("link.pressed.foreground") : + myMouseHover ? UIManager.getColor("link.hover.foreground") : + UIManager.getColor("link.foreground"); + } + + @Override public Color getEffectColor() { + return getForegroundColor(); + } + + @Override public EffectType getEffectType() { + return !isEnabled() || myMouseHover || myMousePressed ? EffectType.LINE_UNDERSCORE : null; + } + + @Override public void setForegroundColor(Color color) { + throw new UnsupportedOperationException(); + } + @Override public void setEffectColor(Color color) { + throw new UnsupportedOperationException(); + } + @Override public void setEffectType(EffectType effectType) { + throw new UnsupportedOperationException(); + } + } }