IDEA-170165 Rework Mac OS focused button and other controls highlighting
@@ -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);
|
||||
|
||||
|
Before Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 191 B |
|
Before Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 95 B |
|
Before Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 204 B |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 187 B |
|
Before Width: | Height: | Size: 333 B |
|
Before Width: | Height: | Size: 289 B |
|
Before Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 319 B |
|
Before Width: | Height: | Size: 861 B |
|
Before Width: | Height: | Size: 408 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 92 B |
|
Before Width: | Height: | Size: 132 B |
|
Before Width: | Height: | Size: 107 B |
|
Before Width: | Height: | Size: 171 B |
|
Before Width: | Height: | Size: 195 B |
|
Before Width: | Height: | Size: 405 B |
|
Before Width: | Height: | Size: 208 B |
|
Before Width: | Height: | Size: 400 B |
|
Before Width: | Height: | Size: 201 B |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 302 B |
|
Before Width: | Height: | Size: 677 B |
|
Before Width: | Height: | Size: 330 B |
|
Before Width: | Height: | Size: 857 B |
|
Before Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 191 B |
|
Before Width: | Height: | Size: 336 B |
|
Before Width: | Height: | Size: 95 B |
|
Before Width: | Height: | Size: 125 B |
|
Before Width: | Height: | Size: 204 B |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 227 B |
|
Before Width: | Height: | Size: 333 B |
|
Before Width: | Height: | Size: 288 B |
|
Before Width: | Height: | Size: 647 B |
|
Before Width: | Height: | Size: 307 B |
|
Before Width: | Height: | Size: 701 B |
|
Before Width: | Height: | Size: 387 B |
|
Before Width: | Height: | Size: 862 B |
|
Before Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 132 B |
|
Before Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 166 B |
|
Before Width: | Height: | Size: 180 B |
|
Before Width: | Height: | Size: 288 B |
|
Before Width: | Height: | Size: 189 B |
|
Before Width: | Height: | Size: 304 B |
|
Before Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 335 B |
|
Before Width: | Height: | Size: 290 B |
|
Before Width: | Height: | Size: 650 B |
|
Before Width: | Height: | Size: 311 B |
|
Before Width: | Height: | Size: 668 B |
|
Before Width: | Height: | Size: 387 B |
|
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);
|
||||
}
|
||||
|
||||
|
||||