IDEA-170165 Rework Mac OS focused button and other controls highlighting

This commit is contained in:
Kirill Kirichenko
2017-04-05 17:57:13 +03:00
parent 2ca7d6f3ee
commit 44ff7a0b51
70 changed files with 131 additions and 82 deletions
@@ -24,6 +24,9 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
/**
* @author nik
@@ -56,6 +59,23 @@ class JreComboboxEditor extends BasicComboBoxEditor {
protected JTextField createEditorComponent() {
JBTextField field = new JBTextField();
field.setBorder(null);
field.addFocusListener(new FocusListener() {
@Override public void focusGained(FocusEvent e) {
update(e);
}
@Override public void focusLost(FocusEvent e) {
update(e);
}
private void update(FocusEvent e) {
Component c = e.getComponent().getParent();
if (c != null) {
c.revalidate();
c.repaint();
}
}
});
return field;
}
@@ -16,6 +16,7 @@
package com.intellij.openapi.ui;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -88,10 +89,11 @@ public class FixedSizeButton extends JButton {
public Dimension getPreferredSize() {
if (myComponent != null) {
int size = myComponent.getPreferredSize().height;
if (myComponent instanceof JComboBox && (UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula())) {
if (myComponent instanceof JComboBox && (!SystemInfo.isMac && UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula())) {
// JComboBox's preferred height is 2px greater than JTextField's one, because
// javax.swing.DefaultListCellRenderer#getNoFocusBorder returns (1,1,1,1) border.
// Decrement to have equal sizes for pretty look when stacked vertically
// Mac default border is computed correctly, so don't account for on Mac.
size -= 2;
}
return new Dimension(size, size);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 861 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 408 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 677 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 857 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 435 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 499 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 307 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 845 B

@@ -15,24 +15,38 @@
*/
package com.intellij.ide.ui.laf.intellij;
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI;
import com.intellij.util.ui.JBUI;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.UIResource;
import java.awt.*;
import static com.intellij.ide.ui.laf.intellij.MacIntelliJButtonUI.ARC_SIZE;
/**
* @author Konstantin Bulenkov
*/
public class MacIntelliJButtonBorder implements Border, UIResource {
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
if (!c.hasFocus() ||
c instanceof JComponent && DarculaButtonUI.isHelpButton((JComponent)c)) return;
Graphics2D g2 = (Graphics2D)g.create();
try {
g2.translate(x, y);
DarculaUIUtil.paintFocusBorder(g2, width, height, ARC_SIZE, true);
} finally {
g2.dispose();
}
}
@Override
public Insets getBorderInsets(Component c) {
return JBUI.insets(2,7).asUIResource();
return JBUI.insets(3, 3).asUIResource();
}
@Override
@@ -16,8 +16,12 @@
package com.intellij.ide.ui.laf.intellij;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.laf.IntelliJLaf;
import com.intellij.ide.ui.laf.darcula.ui.DarculaButtonUI;
import com.intellij.ui.Gray;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
import sun.swing.SwingUtilities2;
import javax.swing.*;
@@ -25,8 +29,8 @@ import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.BasicHTML;
import javax.swing.text.View;
import java.awt.*;
import java.awt.geom.Area;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
/**
* @author Konstantin Bulenkov
@@ -36,11 +40,14 @@ public class MacIntelliJButtonUI extends DarculaButtonUI {
private static Rectangle textRect = new Rectangle();
private static Rectangle iconRect = new Rectangle();
static final int ARC_SIZE = JBUI.scale(6);
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
public static ComponentUI createUI(JComponent c) {
return new MacIntelliJButtonUI();
}
@SuppressWarnings("UseJBColor")
@Override
public void paint(Graphics g, JComponent c) {
if (!(c.getBorder() instanceof MacIntelliJButtonBorder) && !isComboButton(c)) {
@@ -56,86 +63,87 @@ public class MacIntelliJButtonUI extends DarculaButtonUI {
icon.paintIcon(c, g, x, y);
} else {
AbstractButton b = (AbstractButton) c;
String text = layout(b, SwingUtilities2.getFontMetrics(b, g),
b.getWidth(), b.getHeight());
FontMetrics fm = SwingUtilities2.getFontMetrics(b, g);
String text = isSquare(c) ? layout(b, "...", null, fm, b.getWidth(), b.getHeight()) :
layout(b, b.getText(), b.getIcon(), fm, b.getWidth(), b.getHeight());
boolean isFocused = c.hasFocus();
if (isSquare(c)) {
Icon icon = MacIntelliJIconCache.getIcon("browseButton");
int x = (c.getWidth() - icon.getIconWidth()) / 2;
int y = (c.getHeight() - icon.getIconHeight()) / 2;
icon.paintIcon(c, g, x, y);
return;
} else {
int x = isFocused ? 0 : 2;
int y = isFocused ? 0 : (h - viewRect.height) / 2;
Icon icon;
icon = getLeftIcon(b);
icon.paintIcon(b, g, x, y);
x += icon.getIconWidth();
int stop = w - (isFocused ? 0 : 2) - (getRightIcon(b).getIconWidth());
Graphics2D g2 = (Graphics2D)g.create();
try {
g2.translate(0, 0);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, MacUIUtil.USE_QUARTZ ? RenderingHints.VALUE_STROKE_PURE : RenderingHints.VALUE_STROKE_NORMALIZE);
Graphics gg = g.create(0, 0, w, h);
Area area = new Area(new Rectangle2D.Double(x, y, stop - x, h));
area.intersect(new Area(gg.getClip()));
gg.setClip(area);
double lw = UIUtil.isRetina(g2) ? 0.5 : 1.0;
Insets i = c.getBorder().getBorderInsets(c); // ComboButton adds arrow width to the insets, so take the bare border.
icon = getMiddleIcon(b);
while (x < stop) {
icon.paintIcon(b, gg, x, y);
x += icon.getIconWidth();
}
gg.dispose();
icon = getRightIcon(b);
icon.paintIcon(b, g, stop, y);
clearTextShiftOffset();
}
// Paint the Icon
if(b.getIcon() != null) {
paintIcon(g,c,iconRect);
}
if (text != null && !text.isEmpty()){
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
v.paint(g, textRect);
// Draw background
Shape outerRect = new RoundRectangle2D.Double(i.left, i.top, w - (i.left + i.right), h - (i.top + i.bottom),
ARC_SIZE, ARC_SIZE);
Paint p;
if (isDefaultButton(c)) {
p = IntelliJLaf.isGraphite() ?
new GradientPaint(w/2, i.top, new Color(0xb2b2b7), w/2, h - (i.top + i.bottom), new Color(0x929297)) :
new GradientPaint(w/2, i.top, new Color(0x84b0f7), w/2, h - (i.top + i.bottom), new Color(0x4b80fb));
} else if (b.isEnabled()) {
p = Gray.xFF;
} else {
UISettings.setupAntialiasing(g);
paintText(g, b, textRect, text);
p = Gray.xF1;
}
g2.setPaint(p);
g2.fill(outerRect);
// Draw outline
Path2D outline = new Path2D.Double(Path2D.WIND_EVEN_ODD);
outline.append(outerRect, false);
outline.append(new RoundRectangle2D.Double(i.left + lw, i.top + lw,
w - lw*2 - (i.left + i.right),
h - lw*2 - (i.top + i.bottom),
ARC_SIZE - lw, ARC_SIZE - lw), false);
if (isDefaultButton(c)) {
p = IntelliJLaf.isGraphite() ?
new GradientPaint(w/2, i.top, new Color(0xa5a5ab), w/2, h - (i.top + i.bottom), new Color(0x7d7d83)) :
new GradientPaint(w/2, i.top, new Color(0x6d9ff6), w/2, h - (i.top + i.bottom), new Color(0x3861fa));
} else if (b.isEnabled()) {
p = new GradientPaint(w/2, i.top, Gray.xC9, w/2, h - (i.top + i.bottom), Gray.xAC);
} else {
p = new GradientPaint(w/2, i.top, Gray.xD2, w/2, h - (i.top + i.bottom), Gray.xC3);
}
g2.setPaint(p);
g2.fill(outline);
} finally {
g2.dispose();
}
if (isSquare(c)) {
UISettings.setupAntialiasing(g);
paintText(g, b, textRect, text);
} else {
// Paint the Icon
if(b.getIcon() != null) {
paintIcon(g,c,iconRect);
}
if (text != null && !text.isEmpty()){
View v = (View) c.getClientProperty(BasicHTML.propertyKey);
if (v != null) {
v.paint(g, textRect);
} else {
UISettings.setupAntialiasing(g);
paintText(g, b, textRect, text);
}
}
}
}
}
protected static boolean isComboButton(JComponent c) {
private static boolean isComboButton(JComponent c) {
return c instanceof AbstractButton && c.getClientProperty("styleCombo") == Boolean.TRUE;
}
private static Icon getLeftIcon(AbstractButton button) {
return getIcon("Left", button);
}
private static Icon getMiddleIcon(AbstractButton button) {
return getIcon("Middle", button);
}
private static Icon getRightIcon(AbstractButton button) {
return getIcon("Right", button);
}
private static Icon getIcon(String suffix, AbstractButton button) {
boolean isDefault = isDefaultButton(button);
boolean isFocused = button.hasFocus();
boolean combo = isComboButton(button);
String comboPrefix = combo ? "Combo" : "";
String iconName = "button" + comboPrefix + suffix;
return MacIntelliJIconCache.getIcon(iconName, isDefault, isFocused && !combo);
}
private String layout(AbstractButton b, FontMetrics fm,
int width, int height) {
private String layout(AbstractButton b, String text, Icon icon, FontMetrics fm, int width, int height) {
Insets i = b.getInsets();
viewRect.x = i.left;
viewRect.y = i.top;
@@ -151,18 +159,20 @@ public class MacIntelliJButtonUI extends DarculaButtonUI {
// layout the text and icon
return SwingUtilities.layoutCompoundLabel(
b, fm, b.getText(), b.getIcon(),
b, fm, text, icon,
b.getVerticalAlignment(), b.getHorizontalAlignment(),
b.getVerticalTextPosition(), b.getHorizontalTextPosition(),
viewRect, iconRect, textRect,
b.getText() == null ? 0 : b.getIconTextGap());
viewRect, iconRect, textRect, text == null ? 0 : b.getIconTextGap());
}
@Override
public Dimension getPreferredSize(JComponent c) {
Dimension size = super.getPreferredSize(c);
if (c.getBorder() instanceof MacIntelliJButtonBorder || isComboButton(c)) {
return new Dimension(size.width + (isComboButton(c) ? 8 : 16), 27);
if (isHelpButton(c)) {
Icon icon = MacIntelliJIconCache.getIcon("helpButton", false, false);
return new Dimension(icon.getIconWidth(), icon.getIconHeight());
} else if (c.getBorder() instanceof MacIntelliJButtonBorder || isComboButton(c)) {
return new Dimension(size.width + (isComboButton(c) ? 10 : 18), 27);
}
return size;
}
@@ -16,14 +16,16 @@
package com.intellij.ide.ui.laf.intellij;
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder;
import com.intellij.ide.ui.laf.darcula.ui.TextFieldWithPopupHandlerUI;
import com.intellij.openapi.ui.ErrorBorderCapable;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.Gray;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.UIResource;
import java.awt.*;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
@@ -32,7 +34,7 @@ import java.awt.geom.Rectangle2D;
/**
* @author Konstantin Bulenkov
*/
public class MacIntelliJTextBorder extends DarculaTextBorder {
public class MacIntelliJTextBorder implements Border, UIResource, ErrorBorderCapable {
@Override
public Insets getBorderInsets(Component c) {
return JBUI.insets(3, 6).asUIResource();
@@ -84,7 +86,7 @@ public class MacIntelliJTextBorder extends DarculaTextBorder {
}
boolean isFocused(Component c) {
return c.hasFocus();
return c instanceof JScrollPane ? ((JScrollPane)c).getViewport().getView().hasFocus() :c.hasFocus();
}
void clipForBorder(Component c, Graphics2D g2, int width, int height) {
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.plaf.TreeUI;
import javax.swing.tree.DefaultTreeCellRenderer;
import java.awt.*;
import java.awt.geom.GeneralPath;
@@ -141,6 +140,7 @@ public class MacUIUtil {
((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.4f));
}
//noinspection UseJBColor
g.setColor(new Color(100, 100, 100, 200));
g.drawRect(x1, y1, width1 - 1, height1 - 1);
@@ -168,7 +168,7 @@ public class MacUIUtil {
@Override
public Insets getBorderInsets(Component c) {
return new Insets(6, 7, 6, 7);
return new JBInsets(6, 7, 6, 7);
}
@Override
@@ -183,6 +183,7 @@ public class MacUIUtil {
return (Color)o;
}
//noinspection UseJBColor
return new Color(64, 113, 167);
}