IDEA-168315 Component.getGraphics() should not be used to get scale for the HiDPI API

Additionally: HiDPI API methods renaming.
This commit is contained in:
Anton Tarasov
2017-02-16 17:55:00 +03:00
parent 0c56ada8dd
commit 87a6c8dae2
24 changed files with 261 additions and 251 deletions
@@ -229,8 +229,8 @@ class UISettings : BaseState(), PersistentStateComponent<UISettings> {
}
if (fontScale <= 0) {
// Reset font to default on switch from IDEA-managed HiDPI to JDK-managed HiDPI. Doesn't affect OSX.
if (UIUtil.isJDKManagedHiDPI() && !SystemInfo.isMac) fontSize = UIUtil.DEF_SYSTEM_FONT_SIZE.toInt()
// Reset font to default on switch from IDEA-managed HiDPI to JRE-managed HiDPI. Doesn't affect OSX.
if (UIUtil.isJreHiDPIEnabled() && !SystemInfo.isMac) fontSize = UIUtil.DEF_SYSTEM_FONT_SIZE.toInt()
}
else {
fontSize = JBUI.scale(fontSize / fontScale).toInt()
@@ -561,8 +561,8 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
parentNode.setAttribute(VERSION_ATTR, Integer.toString(myVersion));
/**
* FONT_SCALE is used to correctly identify the font size in both the JDK-managed HiDPI mode and
* the IDE-managed HiDPI mode: {@link UIUtil#isJDKManagedHiDPI()}. Also, it helps to distinguish
* FONT_SCALE is used to correctly identify the font size in both the JRE-managed HiDPI mode and
* the IDE-managed HiDPI mode: {@link UIUtil#isJreHiDPIEnabled()}. Also, it helps to distinguish
* the "hidpi-aware" scheme version from the previous one. Namely, the absence of the FONT_SCALE
* attribute in the scheme indicates the previous "hidpi-unaware" scheme and the restored font size
* is reset to default. It's assumed this (transition case) happens only once, after which the IDE
@@ -156,7 +156,7 @@ class ConsoleGutterComponent extends JComponent implements MouseMotionListener {
Graphics2D g2 = (Graphics2D)g;
Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
if (!UIUtil.isJDKManagedHiDPIScreen(g2)) {
if (!UIUtil.isJreHiDPI(this)) {
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
}
@@ -108,8 +108,10 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList
public Insets getBorderInsets(Component c) {
int bottom = (StringUtil.getLineBreakCount(myTextArea.getText()) > 0) ? 2 : UIUtil.isUnderDarcula() ? 1 : 0;
int top = myTextArea.getFontMetrics(myTextArea.getFont()).getHeight() <= 16 ? 2 : 1;
if (JBUI.isHiDPI(c)) bottom = 2;
if (JBUI.isHiDPI(c)) top = 2;
if (JBUI.isUsrHiDPI()) {
bottom = 2;
top = 2;
}
return new JBInsets(top, 0, bottom, 0);
}
@@ -357,13 +359,13 @@ public class SearchTextArea extends NonOpaquePanel implements PropertyChangeList
@Override
String getHistoryButtonConstraints() {
int extraGap = getExtraGap();
return "ay top, gaptop " + extraGap + ", gapleft" + (JBUI.isHiDPI(myTextArea) ? 4 : 0);
return "ay top, gaptop " + extraGap + ", gapleft" + (JBUI.isUsrHiDPI() ? 4 : 0);
}
private int getExtraGap() {
int height = UIUtil.getLineHeight(myTextArea);
Insets insets = myTextArea.getInsets();
return Math.max(JBUI.isHiDPI(myTextArea) ? 0 : 1, (height + insets.top + insets.bottom - JBUI.scale(16)) / 2);
return Math.max(JBUI.isUsrHiDPI() ? 0 : 1, (height + insets.top + insets.bottom - JBUI.scale(16)) / 2);
}
@@ -25,7 +25,6 @@ import com.intellij.openapi.wm.WindowManager;
import com.intellij.ui.ScreenUtil;
import com.intellij.util.containers.hash.LinkedHashMap;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.JBUI.ScaleType;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TObjectIntHashMap;
import org.jdom.Element;
@@ -312,15 +311,15 @@ public class DimensionService implements PersistentStateComponent<Element> {
screen = gd.getDefaultConfiguration().getBounds();
}
float scale = 1f;
if (UIUtil.isJDKManagedHiDPI()) {
scale = JBUI.sysScale(gd);
if (UIUtil.isJreHiDPIEnabled()) {
scale = JBUI.sysScale(gd.getDefaultConfiguration());
// normalize screen bounds
screen.setBounds((int)Math.floor(screen.x * scale), (int)Math.floor(screen.y * scale),
(int)Math.ceil(screen.width * scale), (int)Math.ceil(screen.height * scale));
}
String realKey = key + '.' + screen.x + '.' + screen.y + '.' + screen.width + '.' + screen.height;
if (JBUI.isHiDPI(gd, ScaleType.PIX)) {
int dpi = ((int)(96 * JBUI.pixScale(gd)));
if (JBUI.isPixHiDPI(gd.getDefaultConfiguration())) {
int dpi = ((int)(96 * JBUI.pixScale(gd.getDefaultConfiguration())));
realKey += "@" + dpi + "dpi";
}
return new Pair<>(realKey, scale);
@@ -222,7 +222,7 @@ public enum EffectPainter implements RegionPainter<Font> {
@Override
void paintImage(Graphics2D g, int width, int height, int period) {
Integer round = period <= 2 && !UIUtil.isJDKManagedHiDPIScreen(g) ? null : period;
Integer round = period <= 2 && !UIUtil.isJreHiDPI(g != null ? g.getDeviceConfiguration() : null) ? null : period;
for (int dx = 0; dx < width; dx += period + period) {
RectanglePainter.FILL.paint(g, dx, 0, period, period, round);
}
@@ -271,7 +271,7 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
// [tav] todo: the icon is created in def screen scale
if (UIUtil.isJDKManagedHiDPIScreen()) {
if (UIUtil.isJreHiDPI()) {
final Graphics2D newG = (Graphics2D)g.create(x, y, image.getWidth(), image.getHeight());
float s = JBUI.sysScale();
newG.scale(1/s, 1/s);
@@ -286,12 +286,12 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im
@Override
public int getIconWidth() {
return UIUtil.isJDKManagedHiDPIScreen() ? (int)(image.getWidth() / JBUI.sysScale()) : image.getWidth();
return UIUtil.isJreHiDPI() ? (int)(image.getWidth() / JBUI.sysScale()) : image.getWidth();
}
@Override
public int getIconHeight() {
return UIUtil.isJDKManagedHiDPIScreen() ? (int)(image.getHeight() / JBUI.sysScale()) : image.getHeight();
return UIUtil.isJreHiDPI() ? (int)(image.getHeight() / JBUI.sysScale()) : image.getHeight();
}
};
}
@@ -91,7 +91,7 @@ public class PluginsTableRenderer extends DefaultTableCellRenderer {
myInfoPanel.remove(myBottomPanel);
}
myPanel.setBorder(UIUtil.isJDKManagedHiDPIScreen((Graphics2D)myPanel.getGraphics()) ? new EmptyBorder(4, 3, 4, 3) : new EmptyBorder(2, 3, 2, 3));
myPanel.setBorder(UIUtil.isJreHiDPI(myPanel) ? new EmptyBorder(4, 3, 4, 3) : new EmptyBorder(2, 3, 2, 3));
}
private void createUIComponents() {
@@ -183,7 +183,7 @@ public class DarculaLaf extends BasicLookAndFeel {
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
}
if (SystemInfo.isLinux && JBUI.isHiDPI()) {
if (SystemInfo.isLinux && JBUI.isUsrHiDPI()) {
applySystemFonts(defaults);
}
defaults.put("EditorPane.font", defaults.getFont("TextField.font"));
@@ -237,7 +237,7 @@ public class DarculaLaf extends BasicLookAndFeel {
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
private void patchStyledEditorKit(UIDefaults defaults) {
URL url = getClass().getResource(getPrefix() + (JBUI.isHiDPI() ? "@2x.css" : ".css"));
URL url = getClass().getResource(getPrefix() + (JBUI.isUsrHiDPI() ? "@2x.css" : ".css"));
StyleSheet styleSheet = UIUtil.loadStyleSheet(url);
defaults.put("StyledEditorKit.JBDefaultStyle", styleSheet);
try {
@@ -117,7 +117,7 @@ public class DarculaRadioButtonUI extends MetalRadioButtonUI {
}
if (focus) {
if (UIUtil.isJDKManagedHiDPIScreen(g) || JBUI.isHiDPI(g, JBUI.ScaleType.USR)) {
if (JBUI.isPixHiDPI(c)) {
DarculaUIUtil.paintFocusOval(g, JBUI.scale(1), JBUI.scale(1) + 1, w - JBUI.scale(2), h - JBUI.scale(2));
} else {
DarculaUIUtil.paintFocusOval(g, 0, JBUI.scale(1), w, h);
@@ -32,6 +32,7 @@ import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.keymap.impl.DefaultKeymap;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ResourceUtil;
import com.intellij.util.ui.JBUI;
@@ -45,6 +46,7 @@ import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.StringReader;
@@ -94,7 +96,7 @@ public class TipUIUtil {
StringBuffer text = new StringBuffer(ResourceUtil.loadText(url));
updateShortcuts(text);
updateImages(text, tipLoader);
updateImages(text, tipLoader, browser);
String replaced = text.toString().replace("&productName;", ApplicationNamesInfo.getInstance().getFullProductName());
String major = ApplicationInfo.getInstance().getMajorVersion();
replaced = replaced.replace("&majorVersion;", major);
@@ -140,14 +142,16 @@ public class TipUIUtil {
}
}
private static void updateImages(StringBuffer text, ClassLoader tipLoader) {
private static void updateImages(StringBuffer text, ClassLoader tipLoader, JEditorPane browser) {
final boolean dark = UIUtil.isUnderDarcula();
// if (!dark && !retina) {
// return;
// }
String suffix = "";
if (JBUI.isHiDPI(JBUI.ScaleType.PIX)) suffix += "@2x";
Component af = IdeFrameImpl.getActiveFrame();
Component comp = af != null ? af: browser;
if (JBUI.isPixHiDPI(comp)) suffix += "@2x";
if (dark) suffix += "_dark";
int index = text.indexOf("<img", 0);
while (index != -1) {
@@ -163,7 +167,7 @@ public class TipUIUtil {
URL url = ResourceUtil.getResource(tipLoader, "/tips/", path);
if (url != null) {
String newImgTag = "<img src=\"" + path + "\" ";
if (UIUtil.isJDKManagedHiDPIScreen()) { // [tav] todo: no screen available
if (UIUtil.isJreHiDPI(comp)) {
try {
final BufferedImage image = ImageIO.read(url.openStream());
final int w = (int)(image.getWidth() / JBUI.sysScale());
@@ -65,7 +65,6 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.*;
import com.intellij.util.ui.JBUI.JBUIScaleTrackable;
import com.intellij.util.ui.JBUI.ScaleType;
import gnu.trove.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -229,9 +228,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
.setImageProvider((NullableFunction<DnDActionInfo, DnDImage>)info -> {
Image image = IconUtil.toImage(scaleIcon(getGutterRenderer(info.getPoint()).getIcon()));
// [tav] temp workaround for JRE-224
if (SystemInfo.isWindows && UIUtil.isJDKManagedHiDPI()) {
image = ImageUtil.toBufferedImage(image, !JBUI.isHiDPI((Graphics2D)GraphicsUtil.safelyGetGraphics(myEditor.getComponent()), ScaleType.SYS));
}
boolean inUserScale = SystemInfo.isWindows ? !UIUtil.isJreHiDPI(myEditor.getComponent()) : true;
image = ImageUtil.toBufferedImage(image, inUserScale);
return new DnDImage(image, new Point(image.getWidth(null) / 2, image.getHeight(null) / 2));
})
.enableAsNativeTarget() // required to accept dragging from editor (as editor component doesn't use DnDSupport to implement drag'n'drop)
@@ -302,7 +300,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
paintEditorBackgrounds(g, firstVisibleOffset, lastVisibleOffset);
Object hint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
if (!UIUtil.isJDKManagedHiDPIScreen(g)) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
if (!UIUtil.isJreHiDPI(this)) g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
try {
paintAnnotations(g, startVisualLine, endVisualLine);
@@ -977,7 +975,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
float scale = myEditor.getScale();
if (Math.abs(1f - scale) > 0.10f) {
if (icon instanceof JBUIScaleTrackable) {
((JBUIScaleTrackable)icon).updateJBUIScale((Graphics2D)GraphicsUtil.safelyGetGraphics(this));
((JBUIScaleTrackable)icon).updateJBUIScale(getGraphicsConfiguration());
}
return ((ScalableIcon)icon).scale(scale);
}
@@ -1165,7 +1163,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
int baseHeight,
boolean active) {
Object antialiasing = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
if (SystemInfo.isMac && SystemInfo.JAVA_VERSION.startsWith("1.4.1") || UIUtil.isJDKManagedHiDPIScreen(g)) {
if (SystemInfo.isMac && SystemInfo.JAVA_VERSION.startsWith("1.4.1") || UIUtil.isJreHiDPI(this)) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
@@ -154,7 +154,7 @@ class ImmediatePainter {
//noinspection ConstantConditions
final int caretWidth = isBlockCursor ? editor.getCaretLocations(false)[0].myWidth
: JBUI.scale(caret.getVisualAttributes().getWidth(settings.getLineCursorWidth()));
final float caretShift = isBlockCursor ? 0 : caretWidth == 1 ? 0 : 1 / JBUI.sysScale((Graphics2D)g);
final float caretShift = isBlockCursor ? 0 : caretWidth == 1 ? 0 : 1 / JBUI.sysScale(myEditor.getComponent());
final Rectangle2D caretRectangle = new Rectangle2D.Float((int)(p2x + width2) - caretShift, p2y - topOverhang,
caretWidth, lineHeight + topOverhang + bottomOverhang + (isBlockCursor ? -1 : 0));
@@ -836,7 +836,7 @@ class EditorPainter implements TextDrawingCallback {
int lineWidth = JBUI.scale(attr.getWidth(settings.getLineCursorWidth()));
// fully cover extra character's pixel which can appear due to antialiasing
// see IDEA-148843 for more details
if (x > minX && lineWidth > 1) x -= 1 / JBUI.sysScale(g);
if (x > minX && lineWidth > 1) x -= 1 / JBUI.sysScale(myEditor.getComponent());
g.fill(new Rectangle2D.Float(x, y, lineWidth, nominalLineHeight));
if (myDocument.getTextLength() > 0 && caret != null &&
!myView.getTextLayoutCache().getLineLayout(caret.getLogicalPosition().line).isLtr()) {
@@ -40,7 +40,6 @@ import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
import com.intellij.ui.ScreenUtil;
import com.intellij.util.EventDispatcher;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.JBInsets;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
@@ -743,7 +742,7 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom
int extendedState = updateFrameBounds(frame);
Rectangle rectangle = FrameBoundsConverter.convertToDeviceSpace((Graphics2D)GraphicsUtil.safelyGetGraphics(frame), myFrameBounds);
Rectangle rectangle = FrameBoundsConverter.convertToDeviceSpace(frame.getGraphicsConfiguration(), myFrameBounds);
final Element frameElement = new Element(FRAME_ELEMENT);
frameElement.setAttribute(X_ATTR, Integer.toString(rectangle.x));
@@ -807,8 +806,8 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom
}
/**
* Converts the frame bounds b/w the user space (JDK-managed HiDPI mode) and the device space (IDE-managed HiDPI mode).
* See {@link UIUtil#isJDKManagedHiDPI()}
* Converts the frame bounds b/w the user space (JRE-managed HiDPI mode) and the device space (IDE-managed HiDPI mode).
* See {@link UIUtil#isJreHiDPIEnabled()}
*/
private static class FrameBoundsConverter {
/**
@@ -822,11 +821,11 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom
try {
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
Rectangle devBounds = gd.getDefaultConfiguration().getBounds(); // in user space
scaleUp(devBounds, gd); // to device space
scaleUp(devBounds, gd.getDefaultConfiguration()); // to device space
Rectangle2D.Float devBounds2D = new Rectangle2D.Float(devBounds.x, devBounds.y, devBounds.width, devBounds.height);
Point2D.Float center2d = new Point2D.Float(b.x + b.width / 2, b.y + b.height / 2);
if (devBounds2D.contains(center2d)) {
scaleDown(b, gd);
scaleDown(b, gd.getDefaultConfiguration());
break;
}
}
@@ -837,16 +836,16 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom
}
/**
* @param g the graphics of the device
* @param gc the graphics config
* @param bounds the bounds in the user space
* @return the bounds in the device space
*/
public static Rectangle convertToDeviceSpace(Graphics2D g, @NotNull Rectangle bounds) {
public static Rectangle convertToDeviceSpace(GraphicsConfiguration gc, @NotNull Rectangle bounds) {
Rectangle b = bounds.getBounds();
if (!shouldConvert()) return b;
try {
scaleUp(b, g.getDeviceConfiguration().getDevice());
scaleUp(b, gc);
}
catch (HeadlessException ignore) {
}
@@ -854,23 +853,23 @@ public final class WindowManagerImpl extends WindowManagerEx implements NamedCom
}
private static boolean shouldConvert() {
if (SystemInfo.isLinux || // JDK-managed HiDPI mode is not yet implemented (pending)
SystemInfo.isMac) // JDK-managed HiDPI mode is permanent
if (SystemInfo.isLinux || // JRE-managed HiDPI mode is not yet implemented (pending)
SystemInfo.isMac) // JRE-managed HiDPI mode is permanent
{
return false;
}
if (!UIUtil.isJDKManagedHiDPI()) return false; // device space equals user space
if (!UIUtil.isJreHiDPIEnabled()) return false; // device space equals user space
return true;
}
private static void scaleUp(@NotNull Rectangle bounds, @NotNull GraphicsDevice gd) {
scale(bounds, gd.getDefaultConfiguration().getBounds(), JBUI.sysScale(gd));
private static void scaleUp(@NotNull Rectangle bounds, @NotNull GraphicsConfiguration gc) {
scale(bounds, gc.getBounds(), JBUI.sysScale(gc));
}
private static void scaleDown(@NotNull Rectangle bounds, @NotNull GraphicsDevice gd) {
float scale = JBUI.sysScale(gd);
private static void scaleDown(@NotNull Rectangle bounds, @NotNull GraphicsConfiguration gc) {
float scale = JBUI.sysScale(gc);
assert scale != 0;
scale(bounds, gd.getDefaultConfiguration().getBounds(), 1 / scale);
scale(bounds, gc.getBounds(), 1 / scale);
}
private static void scale(@NotNull Rectangle bounds, @NotNull Rectangle deviceBounds, float scale) {
@@ -188,9 +188,9 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget {
}
UIUtil.drawImage(g, myBufferedImage, 0, 0, null);
if (UIUtil.isJDKManagedHiDPIScreen((Graphics2D)g) && !UIUtil.isUnderDarcula()) {
if (UIUtil.isJreHiDPI(this) && !UIUtil.isUnderDarcula()) {
Graphics2D g2 = (Graphics2D)g.create(0, 0, getWidth(), getHeight());
float s = JBUI.sysScale((Graphics2D)g);
float s = JBUI.sysScale(this);
g2.scale(1/s, 1/s);
g2.setColor(UIUtil.isUnderIntelliJLaF() ? Gray.xC9 : Gray.x91);
g2.drawLine(0, 0, (int)(s * getWidth()), 0);
@@ -83,8 +83,8 @@ public class RecentProjectPanel extends JPanel {
private boolean rectInListCoordinatesContains(Rectangle listCellBounds, Point p) {
int realCloseButtonInset = (UIUtil.isJDKManagedHiDPIScreen((Graphics2D)getGraphics())) ?
(int)(closeButtonInset * JBUI.sysScale((Graphics2D)getGraphics())) : closeButtonInset;
int realCloseButtonInset = (UIUtil.isJreHiDPI(this)) ?
(int)(closeButtonInset * JBUI.sysScale(this)) : closeButtonInset;
Rectangle closeButtonRect = new Rectangle(myCloseButtonForEditor.getX() - realCloseButtonInset,
myCloseButtonForEditor.getY() - realCloseButtonInset,
@@ -1651,8 +1651,9 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
imageGraphics.dispose();
Graphics2D g2d = (Graphics2D)g.create();
try {
if (UIUtil.isJDKManagedHiDPIScreen(g2d)) {
g2d.scale(1/JBUI.sysScale(g2d), 1 / JBUI.sysScale(g2d));
if (UIUtil.isJreHiDPI(this)) {
float s = 1 / JBUI.sysScale(this);
g2d.scale(s, s);
}
UIUtil.drawImage(g2d, makeColorTransparent(image, myFillColor), 0, 0, null);
}
@@ -1716,11 +1717,18 @@ public class BalloonImpl implements Balloon, IdeTooltip.Ui {
private void paintShadow(Graphics graphics) {
if (myShadow != null) {
if (UIUtil.isJDKManagedHiDPIScreen((Graphics2D)graphics)) {
graphics = graphics.create();
((Graphics2D)graphics).scale(1/JBUI.sysScale((Graphics2D)graphics), 1/JBUI.sysScale((Graphics2D)graphics));
Graphics2D g2d = (Graphics2D)graphics;
try {
if (UIUtil.isJreHiDPI(this)) {
g2d = (Graphics2D)graphics.create();
float s = 1 / JBUI.sysScale(this);
g2d.scale(s, s);
}
UIUtil.drawImage(g2d, myShadow.getImage(), myShadow.getX(), myShadow.getY(), null);
}
finally {
if (g2d != graphics) g2d.dispose();
}
UIUtil.drawImage(graphics, myShadow.getImage(), myShadow.getX(), myShadow.getY(), null);
}
}
@@ -285,7 +285,7 @@ public final class IconLoader {
if (icon instanceof CachedImageIcon) {
disabledIcon = ((CachedImageIcon)icon).asDisabledIcon();
} else {
final float scale = UIUtil.isJDKManagedHiDPIScreen() ? JBUI.sysScale() : 1f; // [tav] todo: no screen available
final float scale = UIUtil.isJreHiDPI() ? JBUI.sysScale() : 1f; // [tav] todo: no screen available
@SuppressWarnings("UndesirableClassUsage")
BufferedImage image = new BufferedImage((int)(scale * icon.getIconWidth()), (int)(scale * icon.getIconHeight()), BufferedImage.TYPE_INT_ARGB);
final Graphics2D graphics = image.createGraphics();
@@ -298,7 +298,7 @@ public final class IconLoader {
graphics.dispose();
Image img = ImageUtil.filter(image, UIUtil.getGrayFilter());
if (UIUtil.isJDKManagedHiDPIScreen()) img = RetinaImage.createFrom(img, scale, null);
if (UIUtil.isJreHiDPI()) img = RetinaImage.createFrom(img, scale, null);
disabledIcon = new JBImageIcon(img);
}
@@ -392,9 +392,9 @@ public final class IconLoader {
}
@Override
public boolean updateJBUIScale(Graphics2D g) {
if (needUpdateJBUIScale(g)) {
getRealIcon(g); // force update
public boolean updateJBUIScale(GraphicsConfiguration gc) {
if (needUpdateJBUIScale(gc)) {
getRealIcon(gc); // force update
return true;
}
return false;
@@ -406,12 +406,12 @@ public final class IconLoader {
}
@NotNull
private synchronized ImageIcon getRealIcon(@Nullable Graphics g) {
if (!isValid() || needUpdateJBUIScale((Graphics2D)g)) {
private synchronized ImageIcon getRealIcon(@Nullable GraphicsConfiguration gc) {
if (!isValid() || needUpdateJBUIScale(gc)) {
if (isLoaderDisabled()) return EMPTY_ICON;
myRealIcon = null;
dark = USE_DARK_ICONS;
super.updateJBUIScale((Graphics2D)g);
super.updateJBUIScale(gc);
setGlobalFilter(IMAGE_FILTER);
if (!isValid()) myScaledIconsCache.clear();
if (numberOfPatchers != ourPatchers.size()) {
@@ -460,7 +460,7 @@ public final class IconLoader {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
getRealIcon(g).paintIcon(c, g, x, y);
getRealIcon(c != null ? c.getGraphicsConfiguration() : null).paintIcon(c, g, x, y);
}
@Override
@@ -543,7 +543,7 @@ public final class IconLoader {
Image image = getOrLoadOrigImage(needRetinaImage);
if (image == null) return null;
if (!UIUtil.isJDKManagedHiDPI() && needRetinaImage) {
if (!UIUtil.isJreHiDPIEnabled() && needRetinaImage) {
instanceScale = effectiveScale / 2f; // the image is 2x raw BufferedImage, compensate it
}
@@ -576,7 +576,7 @@ public final class IconLoader {
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
final Icon icon = getOrComputeIcon((Graphics2D)g);
final Icon icon = getOrComputeIcon(c != null ? c.getGraphicsConfiguration() : null);
if (icon != null) {
icon.paintIcon(c, g, x, y);
}
@@ -598,10 +598,10 @@ public final class IconLoader {
return getOrComputeIcon(null);
}
protected final synchronized Icon getOrComputeIcon(@Nullable Graphics2D g) {
if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || needUpdateJBUIScale(g) || filter != IMAGE_FILTER || numberOfPatchers != ourPatchers.size()) {
protected final synchronized Icon getOrComputeIcon(@Nullable GraphicsConfiguration gc) {
if (!myWasComputed || isDarkVariant != USE_DARK_ICONS || needUpdateJBUIScale(gc) || filter != IMAGE_FILTER || numberOfPatchers != ourPatchers.size()) {
isDarkVariant = USE_DARK_ICONS;
updateJBUIScale(g);
updateJBUIScale(gc);
filter = IMAGE_FILTER;
myWasComputed = true;
numberOfPatchers = ourPatchers.size();
@@ -224,7 +224,7 @@ public class ImageLoader implements Serializable {
return with(new ImageConverter() {
@Override
public Image convert(Image source, ImageDesc desc) {
if (source != null && UIUtil.isJDKManagedHiDPI() && desc.scale > 1) {
if (source != null && UIUtil.isJreHiDPIEnabled() && desc.scale > 1) {
return RetinaImage.createFrom(source, (int)desc.scale, ourComponent);
}
return source;
@@ -279,7 +279,7 @@ public class ImageLoader implements Serializable {
/**
* Loads an image by the passed url in scale (1x, 2x, ...) possibly closed to the passed JBUI pix scale,
* then simply returns it in the JDK-managed HiDPI mode, otherwise scales the image
* then simply returns it in the JRE-managed HiDPI mode, otherwise scales the image
* according to the passed scale and returns.
*/
@Nullable
@@ -287,10 +287,10 @@ public class ImageLoader implements Serializable {
final float scaleFactor = adjustScaleFactor(allowFloatScaling, pixScale); // valid for Retina as well
// We can't check all 3rd party plugins and convince the authors to add @2x icons.
// (scaleFactor > 1.0) != isJDKManagedHiDPI() => we should scale images manually.
// Note we never scale images on JDKManagedHiDPI displays because scaling is handled by the system.
// In IDE-managed HiDPI mode with (scaleFactor > 1.0) we should scale images manually.
// Note we never scale images in JRE-managed HiDPI mode because scaling is handled by JRE.
final boolean scaleImages = (scaleFactor > 1.0f && !UIUtil.isJDKManagedHiDPI());
final boolean scaleImages = (scaleFactor > 1.0f && !UIUtil.isJreHiDPIEnabled());
// Prefer retina images for HiDPI scale, because downscaling
// retina images provides a better result than upscaling non-retina images.
@@ -43,11 +43,7 @@ public class JBHiDPIScaledImage extends BufferedImage {
* @param type the type
*/
public JBHiDPIScaledImage(int width, int height, int type) {
super((int)(width * JBUI.sysScale()), (int)(height * JBUI.sysScale()), type);
myImage = null;
myUserWidth = width;
myUserHeight = height;
myScale = JBUI.sysScale();
this((GraphicsConfiguration)null, width, height, type);
}
/**
@@ -58,12 +54,24 @@ public class JBHiDPIScaledImage extends BufferedImage {
* @param height the height in user coordinate space
* @param type the type
*/
public JBHiDPIScaledImage(@NotNull Graphics2D g, int width, int height, int type) {
super((int)(width * JBUI.sysScale(g)), (int)(height * JBUI.sysScale(g)), type);
public JBHiDPIScaledImage(@Nullable Graphics2D g, int width, int height, int type) {
this(g != null ? g.getDeviceConfiguration() : null, width, height, type);
}
/**
* Creates a scaled HiDPI-aware BufferedImage, targeting the graphics config.
*
* @param gc the graphics config which provides the target scale
* @param width the width in user coordinate space
* @param height the height in user coordinate space
* @param type the type
*/
public JBHiDPIScaledImage(@Nullable GraphicsConfiguration gc, int width, int height, int type) {
super((int)(width * JBUI.sysScale(gc)), (int)(height * JBUI.sysScale(gc)), type);
myImage = null;
myUserWidth = width;
myUserHeight = height;
myScale = JBUI.sysScale(g);
myScale = JBUI.sysScale(gc);
}
/**
@@ -83,17 +83,22 @@ public class RetinaImage { // [tav] todo: create HiDPIImage class
@NotNull
public static BufferedImage create(Graphics2D g, final int width, int height, int type) {
return create(g, null, width, height, type);
return create(g != null ? g.getDeviceConfiguration() : null, null, width, height, type);
}
@NotNull
private static BufferedImage create(Graphics2D g, Image image, final int width, int height, int type) {
public static BufferedImage create(GraphicsConfiguration gc, final int width, int height, int type) {
return create(gc, null, width, height, type);
}
@NotNull
private static BufferedImage create(GraphicsConfiguration gc, Image image, final int width, int height, int type) {
if (SystemInfo.isAppleJvm) {
return AppleHiDPIScaledImage.create(width, height, type);
} else {
if (image == null) {
return g == null ? new JBHiDPIScaledImage(width, height, type) :
new JBHiDPIScaledImage(g, width, height, type);
return gc == null ? new JBHiDPIScaledImage(width, height, type) :
new JBHiDPIScaledImage(gc, width, height, type);
} else {
return new JBHiDPIScaledImage(image, width, height, type);
}
+85 -120
View File
@@ -26,7 +26,6 @@ import com.intellij.util.keyFMap.KeyFMap;
import com.intellij.util.ui.components.BorderLayoutPanel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.awt.image.BufferedImageGraphicsConfig;
import javax.swing.*;
import javax.swing.border.Border;
@@ -53,17 +52,17 @@ public class JBUI {
*
* 1) IDE-managed HiDPI mode.
*
* Supported for backward compatibility until complete transition to the JDK-managed HiDPI mode happens.
* Supported for backward compatibility until complete transition to the JRE-managed HiDPI mode happens.
* In this mode there's a single coordinate space and the whole UI is scaled by the IDE guided by the
* user scale factor ({@link #USR}).
*
* 2) JDK-managed HiDPI mode.
* 2) JRE-managed HiDPI mode.
*
* In this mode the JDK scales graphics prior to drawing it on the device. So, there're two coordinate
* In this mode the JRE scales graphics prior to drawing it on the device. So, there're two coordinate
* spaces: the user space and the device space. The system scale factor ({@link #SYS}) defines the
* transform b/w the spaces. The UI size metrics (windows, controls, fonts height) are in the user
* coordinate space. Though, the raster images should be aware of the device scale in order to meet
* HiDPI. (For instance, JDK on a Mac Retina monitor device works in the JDK-managed HiDPI mode,
* HiDPI. (For instance, JRE on a Mac Retina monitor device works in the JRE-managed HiDPI mode,
* transforming graphics to the double-scaled device coordinate space)
*
* The IDE operates the scale factors of the following types:
@@ -72,11 +71,14 @@ public class JBUI {
* 2) The system (monitor device) scale factor: {@link #SYS}
* 3) The pixel scale factor: {@link #PIX}
*
* @see UIUtil#isJDKManagedHiDPI()
* @see UIUtil#isJDKManagedHiDPIScreen()
* @see UIUtil#isJDKManagedHiDPIScreen(Graphics2D)
* @see UIUtil#isJreHiDPIEnabled()
* @see UIUtil#isJreHiDPI()
* @see UIUtil#isJreHiDPI(GraphicsConfiguration)
* @see JBUI#isUsrHiDPI()
* @see JBUI#isPixHiDPI(GraphicsConfiguration)
* @see UIUtil#drawImage(Graphics, Image, int, int, int, int, ImageObserver)
* @see UIUtil#createImage(Graphics, int, int, int)
* @see UIUtil#createImage(GraphicsConfiguration, int, int, int)
* @see UIUtil#createImage(int, int, int)
*/
public enum ScaleType {
@@ -86,11 +88,11 @@ public class JBUI {
*
* The user scale value depends on which HiDPI mode is enabled. In the IDE-managed HiDPI mode the
* user scale "includes" the default system scale and simply equals it with the default UI font size.
* In the JDK-managed HiDPI mode the user scale is independent of the system scale and equals 1.0
* In the JRE-managed HiDPI mode the user scale is independent of the system scale and equals 1.0
* with the default UI font size. In case the default UI font size changes, the user scale changes
* proportionally in both the HiDPI modes.
*
* In the IDE-managed HiDPI mode the user scale completely defines the UI scale. In the JDK-managed
* In the IDE-managed HiDPI mode the user scale completely defines the UI scale. In the JRE-managed
* HiDPI mode the user scale can be considered a supplementary scale taking effect in cases like
* the IDE Presentation Mode and when the default UI scale is changed by the user.
*
@@ -106,28 +108,28 @@ public class JBUI {
* there's always a single default system scale factor corresponding to the default device. And it's
* the only system scale available in the IDE-managed HiDPI mode.
*
* In the JDK-managed HiDPI mode, the system scale defines the scale of the transform b/w the user
* and the device coordinate spaces performed by the JDK.
* In the JRE-managed HiDPI mode, the system scale defines the scale of the transform b/w the user
* and the device coordinate spaces performed by the JRE.
*
* @see #sysScale()
* @see #sysScale(Graphics2D)
* @see #sysScale(GraphicsDevice)
* @see #sysScale(GraphicsConfiguration)
* @see #sysScale(Component)
*/
SYS,
/**
* The pixel scale factor "combines" both the user and the system scale factors and defines the
* effective scale of the whole UI.
*
* For instance, on Mac Retina monitor (JDK-managed HiDPI) in the Presentation mode (which, say,
* For instance, on Mac Retina monitor (JRE-managed HiDPI) in the Presentation mode (which, say,
* doubles the UI scale) the pixel scale would equal 4.0. The value is the product of the user
* scale 2.0 and the system scale 2.0. In the IDE-managed HiDPI mode, the pixel scale always equals
* the user scale.
*
* @see #pixScale()
* @see #pixScale(Graphics2D)
* @see #pixScale(GraphicsDevice)
* @see #pixScale(GraphicsConfiguration)
* @see #pixScale(Component)
* @see #pixScale(GraphicsConfiguration, float)
* @see #pixScale(float)
* @see #pixScale(Graphics2D, float)
*/
PIX;
@@ -145,7 +147,7 @@ public class JBUI {
private static float userScaleFactor;
static {
setUserScaleFactor(UIUtil.isJDKManagedHiDPI() ? 1f : SYSTEM_SCALE_FACTOR);
setUserScaleFactor(UIUtil.isJreHiDPIEnabled() ? 1f : SYSTEM_SCALE_FACTOR);
}
/**
@@ -171,13 +173,13 @@ public class JBUI {
return SYSTEM_SCALE_FACTOR;
}
if (UIUtil.isJDKManagedHiDPI()) {
if (UIUtil.isJreHiDPIEnabled()) {
GraphicsDevice gd = null;
try {
gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
} catch (HeadlessException ignore) {}
if (gd != null) {
return sysScale(gd);
return sysScale(gd.getDefaultConfiguration());
}
return 1.0f;
}
@@ -198,38 +200,35 @@ public class JBUI {
* In the IDE-managed HiDPI mode defaults to {@link #sysScale()}
*/
public static float sysScale(JBUIScaleTrackable trackable) {
if (UIUtil.isJDKManagedHiDPI() && trackable != null) {
if (UIUtil.isJreHiDPIEnabled() && trackable != null) {
return trackable.getJBUIScale(ScaleType.SYS);
}
return sysScale();
}
/**
* Returns the system scale factor, corresponding to the provided graphics context.
* Returns the system scale factor, corresponding to the graphics configuration
* In the IDE-managed HiDPI mode defaults to {@link #sysScale()}
*/
public static float sysScale(@Nullable Graphics2D g) {
if (UIUtil.isJDKManagedHiDPI() && g != null) {
GraphicsConfiguration conf = g.getDeviceConfiguration();
if (conf instanceof BufferedImageGraphicsConfig) {
// take BI's scale directly, not inspecting the device
return (float)g.getTransform().getScaleX();
public static float sysScale(@Nullable GraphicsConfiguration gc) {
if (UIUtil.isJreHiDPIEnabled() && gc != null) {
if (SystemInfo.isMac && UIUtil.isJreHiDPI_earlierVersion()) {
if (gc.getDevice().getType() == GraphicsDevice.TYPE_RASTER_SCREEN) {
return UIUtil.DetectRetinaKit.isOracleMacRetinaDevice(gc.getDevice()) ? 2f : 1f;
}
}
if (conf != null) return sysScale(conf.getDevice());
return (float)gc.getDefaultTransform().getScaleX();
}
return sysScale();
}
/**
* Returns the system scale factor, corresponding to the provided device.
* Returns the system scale factor, corresponding to the device the component is tied to.
* In the IDE-managed HiDPI mode defaults to {@link #sysScale()}
*/
public static float sysScale(@Nullable GraphicsDevice gd) {
if (UIUtil.isJDKManagedHiDPI() && gd != null) {
if (SystemInfo.isMac && UIUtil.isJDKManagedHiDPI_earlierVersion()) {
return UIUtil.DetectRetinaKit.isOracleMacRetinaDevice(gd) ? 2f : 1f;
}
return (float)gd.getDefaultConfiguration().getDefaultTransform().getScaleX();
public static float sysScale(@Nullable Component comp) {
if (comp != null) {
return sysScale(comp.getGraphicsConfiguration());
}
return sysScale();
}
@@ -238,7 +237,7 @@ public class JBUI {
* Returns the pixel scale factor, corresponding to the default monitor device.
*/
public static float pixScale() {
return UIUtil.isJDKManagedHiDPI() ? sysScale() * scale(1f) : scale(1f);
return UIUtil.isJreHiDPIEnabled() ? sysScale() * scale(1f) : scale(1f);
}
/**
@@ -249,33 +248,33 @@ public class JBUI {
}
/**
* Returns "f" scaled by pixScale(g).
* Returns "f" scaled by pixScale(gc).
*/
public static float pixScale(@Nullable Graphics2D g, float f) {
return pixScale(g) * f;
public static float pixScale(@Nullable GraphicsConfiguration gc, float f) {
return pixScale(gc) * f;
}
/**
* Returns the pixel scale factor based on the JBUIScaleTrackable.
*/
public static float pixScale(@NotNull JBUIScaleTrackable trackable) {
return UIUtil.isJDKManagedHiDPI() ? sysScale(trackable) * trackable.getJBUIScale(ScaleType.USR) : trackable.getJBUIScale(ScaleType.USR);
return UIUtil.isJreHiDPIEnabled() ? sysScale(trackable) * trackable.getJBUIScale(ScaleType.USR) : trackable.getJBUIScale(ScaleType.USR);
}
/**
* Returns the pixel scale factor, corresponding to the provided graphics context.
* Returns the pixel scale factor, corresponding to the provided configuration.
* In the IDE-managed HiDPI mode defaults to {@link #pixScale()}
*/
public static float pixScale(@Nullable Graphics2D g) {
return g != null ? pixScale(g.getDeviceConfiguration().getDevice()) : pixScale();
public static float pixScale(@Nullable GraphicsConfiguration gc) {
return UIUtil.isJreHiDPIEnabled() ? sysScale(gc) * scale(1f) : scale(1f);
}
/**
* Returns the pixel scale factor, corresponding to the provided graphics device.
* Returns the pixel scale factor, corresponding to the device the provided component is tied to.
* In the IDE-managed HiDPI mode defaults to {@link #pixScale()}
*/
public static float pixScale(@Nullable GraphicsDevice gd) {
return UIUtil.isJDKManagedHiDPI() ? sysScale(gd) * scale(1f) : scale(1f);
public static float pixScale(@Nullable Component comp) {
return pixScale(comp != null ? comp.getGraphicsConfiguration() : null);
}
private static void setUserScaleFactorProperty(float scale) {
@@ -404,78 +403,44 @@ public class JBUI {
}
/**
* @deprecated use {@link #isHiDPI(Graphics2D, ScaleType)}, {@link #isHiDPI(ScaleType)}
* @deprecated use {@link #isUsrHiDPI()} instead
*/
@Deprecated
public static boolean isHiDPI() {
return isHiDPI(ScaleType.USR);
return isUsrHiDPI();
}
/**
* Returns whether the scale factor associated with the graphics context assumes HiDPI-awareness.
*
* @param g the graphics context
* @param type the type of the scale factor
* @return whether HiDPI-awareness is assumed for the scale factor
* Returns whether the {@link ScaleType#USR} scale factor assumes HiDPI-awareness.
* An equivalent of {@code isHiDPI(scale(1f))}
*/
public static boolean isHiDPI(@Nullable Graphics2D g, ScaleType type) {
return isHiDPI(g == null ? null : g.getDeviceConfiguration().getDevice(), type);
public static boolean isUsrHiDPI() {
return isHiDPI(scale(1f));
}
/**
* Returns whether the scale factor associated with the graphics device assumes HiDPI-awareness.
*
* @param gd the graphics device
* @param type the type of the scale factor
* @return whether HiDPI-awareness is assumed for the scale factor
* Returns whether the {@link ScaleType#PIX} scale factor assumes HiDPI-awareness in the provided graphics config.
* An equivalent of {@code isHiDPI(pixScale(gc))}
*/
public static boolean isHiDPI(@Nullable GraphicsDevice gd, ScaleType type) {
switch (type) {
case USR:
return isHiDPI(scale(1f));
case SYS:
return isHiDPI(sysScale(gd));
case PIX:
return isHiDPI(pixScale(gd));
default:
return false;
}
public static boolean isPixHiDPI(@Nullable GraphicsConfiguration gc) {
return isHiDPI(pixScale(gc));
}
/**
* Returns whether the scale factor assumes HiDPI-awareness.
*
* @param scale the scale factor
* @return whether HiDPI-awareness is assumed for the scale factor
* Returns whether the {@link ScaleType#PIX} scale factor assumes HiDPI-awareness in the provided component's device.
* An equivalent of {@code isHiDPI(pixScale(comp))}
*/
public static boolean isPixHiDPI(@Nullable Component comp) {
return isHiDPI(pixScale(comp));
}
/**
* Returns whether the provided scale assumes HiDPI-awareness.
*/
public static boolean isHiDPI(float scale) {
return scale > 1f;
}
/**
* Equivalent of {@link #isHiDPI(Graphics2D, ScaleType)} called for the graphics of the default screen device.
*
* @see #isHiDPI(Graphics2D, ScaleType)
*/
public static boolean isHiDPI(ScaleType type) {
return isHiDPI((GraphicsDevice)null, type);
}
/**
* Equivalent of {@link #isHiDPI(Graphics2D, ScaleType.USR)} called for the graphics of the specified component.
*
* @see #isHiDPI(Graphics2D, ScaleType)
* @param component if it's {@code null} the graphics of the default screen device will be used
*/
public static boolean isHiDPI(@Nullable Component component) {
Graphics graphics = component != null? component.getGraphics() : null;
try {
return isHiDPI((Graphics2D)graphics, ScaleType.USR);
} finally {
if (graphics != null) graphics.dispose();
}
}
public static class Fonts {
public static JBFont label() {
return JBFont.create(UIManager.getFont("Label.font"), false);
@@ -578,9 +543,9 @@ public class JBUI {
}
static float currentJBUIScale() {
// We don't JBUI-scale images in JDK-managed HiDPI mode, see comments in ImageLoader.loadFromUrl(..)
// We don't JBUI-scale images in JRE-managed HiDPI mode, see comments in ImageLoader.loadFromUrl(..)
// So, make icons JBUI-scale conformant.
return UIUtil.isJDKManagedHiDPI() ? 1f : scale(1f);
return UIUtil.isJreHiDPIEnabled() ? 1f : scale(1f);
}
/**
@@ -752,12 +717,12 @@ public class JBUI {
boolean updateJBUIScale();
/**
* Updates all the scale factors based on the provided graphics (device).
* Updates all the scale factors based on the provided graphics configuration.
*
* @param g the graphics, if null defaults to {@link #updateJBUIScale()}
* @param gc the graphics config, if null defaults to {@link #updateJBUIScale()}
* @return true if any of the tracked scale factors was updated
*/
boolean updateJBUIScale(@Nullable Graphics2D g);
boolean updateJBUIScale(@Nullable GraphicsConfiguration gc);
/**
* @return true if tracked user scale should be updated
@@ -765,10 +730,10 @@ public class JBUI {
boolean needUpdateJBUIScale();
/**
* @param g the graphics, if null defaults to {@link #needUpdateJBUIScale()}
* @param gc the graphics config, if null defaults to {@link #needUpdateJBUIScale()}
* @return true if any of the tracked scale factors should be updated
*/
boolean needUpdateJBUIScale(@Nullable Graphics2D g);
boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc);
/**
* @param type the type of the scale
@@ -809,9 +774,9 @@ public class JBUI {
}
@Override
public boolean updateJBUIScale(@Nullable Graphics2D g) {
public boolean updateJBUIScale(@Nullable GraphicsConfiguration gc) {
boolean res = updateJBUIScale();
if (g != null) res = res || updateJBUIScale(sysScale(g), ScaleType.SYS);
if (gc != null) res = res || updateJBUIScale(sysScale(gc), ScaleType.SYS);
return res;
}
@@ -825,8 +790,8 @@ public class JBUI {
}
@Override
public boolean needUpdateJBUIScale(@Nullable Graphics2D g) {
return needUpdateJBUIScale() || g != null && needUpdateJBUIScale(sysScale(g), ScaleType.SYS);
public boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc) {
return needUpdateJBUIScale() || gc != null && needUpdateJBUIScale(sysScale(gc), ScaleType.SYS);
}
@Override
@@ -851,8 +816,8 @@ public class JBUI {
}
@Override
public boolean updateJBUIScale(@Nullable Graphics2D g) {
return myJBUIScaleDelegate.updateJBUIScale(g);
public boolean updateJBUIScale(@Nullable GraphicsConfiguration gc) {
return myJBUIScaleDelegate.updateJBUIScale(gc);
}
@Override
@@ -861,8 +826,8 @@ public class JBUI {
}
@Override
public boolean needUpdateJBUIScale(@Nullable Graphics2D g) {
return myJBUIScaleDelegate.needUpdateJBUIScale(g);
public boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc) {
return myJBUIScaleDelegate.needUpdateJBUIScale(gc);
}
@Override
@@ -891,8 +856,8 @@ public class JBUI {
}
@Override
public boolean updateJBUIScale(@Nullable Graphics2D g) {
return myJBUIScaleDelegate.updateJBUIScale(g);
public boolean updateJBUIScale(@Nullable GraphicsConfiguration gc) {
return myJBUIScaleDelegate.updateJBUIScale(gc);
}
@Override
@@ -901,8 +866,8 @@ public class JBUI {
}
@Override
public boolean needUpdateJBUIScale(@Nullable Graphics2D g) {
return myJBUIScaleDelegate.needUpdateJBUIScale(g);
public boolean needUpdateJBUIScale(@Nullable GraphicsConfiguration gc) {
return myJBUIScaleDelegate.needUpdateJBUIScale(gc);
}
@Override
@@ -339,36 +339,43 @@ public class UIUtil {
}
/**
* Returns whether the JDK-managed HiDPI mode is enabled and the default monitor device is HiDPI.
* (Equivalent of {@link #isRetina()} on macOS)
* Returns whether the JRE-managed HiDPI mode is enabled and the default monitor device is HiDPI.
* (analogue of {@link #isRetina()} on macOS)
*/
public static boolean isJDKManagedHiDPIScreen() {
return isJDKManagedHiDPI() && JBUI.sysScale() > 1.0f;
public static boolean isJreHiDPI() {
return isJreHiDPI((GraphicsConfiguration)null);
}
/**
* Returns whether the JDK-managed HiDPI mode is enabled and the graphics device is HiDPI.
* (Equivalent of {@link #isRetina(Graphics2D)} on macOS)
* Returns whether the JRE-managed HiDPI mode is enabled and the graphics configuration represents a HiDPI device.
* (analogue of {@link #isRetina(Graphics2D)} on macOS)
*/
public static boolean isJDKManagedHiDPIScreen(Graphics2D g) {
return isJDKManagedHiDPI() && JBUI.sysScale(g) > 1.0f;
public static boolean isJreHiDPI(@Nullable GraphicsConfiguration gc) {
return isJreHiDPIEnabled() && JBUI.isHiDPI(JBUI.sysScale(gc));
}
private static Boolean jdkManagedHiDPI;
private static boolean jdkManagedHiDPI_earlierVersion;
/**
* Returns whether the JRE-managed HiDPI mode is enabled and the provided component is tied to a HiDPI device.
*/
public static boolean isJreHiDPI(@Nullable Component comp) {
return isJreHiDPI(comp != null ? comp.getGraphicsConfiguration() : null);
}
private static Boolean jreHiDPI;
private static boolean jreHiDPI_earlierVersion;
/**
* Returns whether the JDK-managed HiDPI mode is enabled.
* Returns whether the JRE-managed HiDPI mode is enabled.
* (True for macOS JDK >= 7.10 versions)
*
* @see JBUI.ScaleType
*/
public static boolean isJDKManagedHiDPI() {
if (jdkManagedHiDPI != null) {
return jdkManagedHiDPI;
public static boolean isJreHiDPIEnabled() {
if (jreHiDPI != null) {
return jreHiDPI;
}
jdkManagedHiDPI = false;
jdkManagedHiDPI_earlierVersion = true;
jreHiDPI = false;
jreHiDPI_earlierVersion = true;
if (SystemInfo.isLinux) {
return false; // pending support
}
@@ -376,25 +383,25 @@ public class UIUtil {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
if (ge instanceof SunGraphicsEnvironment) {
Method m = ReflectionUtil.getDeclaredMethod(SunGraphicsEnvironment.class, "isUIScaleOn");
jdkManagedHiDPI = (Boolean)m.invoke(ge);
jdkManagedHiDPI_earlierVersion = false;
jreHiDPI = (Boolean)m.invoke(ge);
jreHiDPI_earlierVersion = false;
}
} catch (Throwable ignore) {
}
if (SystemInfo.isMac) {
return jdkManagedHiDPI = (SystemInfo.isAppleJvm ? false : true);
return jreHiDPI = (SystemInfo.isAppleJvm ? false : true);
}
return jdkManagedHiDPI;
return jreHiDPI;
}
/**
* Indicates earlier JBSDK version, not containing HiDPI changes.
* On macOS that JBSDK supports jdkManagedHiDPI, but it's not capable to provide device scale
* On macOS such JBSDK supports jreHiDPI, but it's not capable to provide device scale
* via GraphicsDevice transform matrix (the scale should be retrieved via DetectRetinaKit).
*/
static boolean isJDKManagedHiDPI_earlierVersion() {
isJDKManagedHiDPI();
return jdkManagedHiDPI_earlierVersion;
static boolean isJreHiDPI_earlierVersion() {
isJreHiDPIEnabled();
return jreHiDPI_earlierVersion;
}
/**
@@ -1715,7 +1722,7 @@ public class UIUtil {
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.7f));
g.setPaint(getGradientPaint(startXf, 2, c1, startXf, height - 5, c2));
if (isJDKManagedHiDPIScreen()) {
if (isJreHiDPI(g.getDeviceConfiguration())) {
GraphicsConfig c = GraphicsUtil.setupRoundedBorderAntialiasing(g);
g.fill(new RoundRectangle2D.Float(startXf, 2, endXf - startXf, height - 4, 5, 5));
c.restore();
@@ -1812,7 +1819,7 @@ public class UIUtil {
g.setColor(getPanelBackground());
g.fillRect(x, 0, width, height);
boolean jmHiDPI = isJDKManagedHiDPIScreen((Graphics2D)g);
boolean jmHiDPI = isJreHiDPI(((Graphics2D)g).getDeviceConfiguration());
if (jmHiDPI) {
((Graphics2D)g).setStroke(new BasicStroke(2f));
}
@@ -1904,13 +1911,32 @@ public class UIUtil {
*/
@NotNull
public static BufferedImage createImage(int width, int height, int type) {
if (isJDKManagedHiDPIScreen()) {
if (isJreHiDPI()) {
return RetinaImage.create(width, height, type);
}
//noinspection UndesirableClassUsage
return new BufferedImage(width, height, type);
}
/**
* Creates a HiDPI-aware BufferedImage in the graphics config scale.
*
* @param gc the graphics config
* @param width the width in user coordinate space
* @param height the height in user coordinate space
* @param type the type of the image
*
* @return a HiDPI-aware BufferedImage in the graphics scale
*/
@NotNull
public static BufferedImage createImage(GraphicsConfiguration gc, int width, int height, int type) {
if (isJreHiDPI(gc)) {
return RetinaImage.create(gc, width, height, type);
}
//noinspection UndesirableClassUsage
return new BufferedImage(width, height, type);
}
/**
* Creates a HiDPI-aware BufferedImage in the graphics device scale.
*
@@ -1924,12 +1950,7 @@ public class UIUtil {
@NotNull
public static BufferedImage createImage(Graphics g, int width, int height, int type) {
if (g instanceof Graphics2D) {
Graphics2D g2d = (Graphics2D)g;
if (isJDKManagedHiDPIScreen(g2d)) {
return RetinaImage.create(g2d, width, height, type);
}
//noinspection UndesirableClassUsage
return new BufferedImage(width, height, type);
return createImage(((Graphics2D)g).getDeviceConfiguration(), width, height, type);
}
return createImage(width, height, type);
}
@@ -1947,7 +1968,7 @@ public class UIUtil {
@NotNull
public static BufferedImage createImage(Component comp, int width, int height, int type) {
return comp != null ?
createImage(GraphicsUtil.safelyGetGraphics(comp), width, height, type) :
createImage(comp != null ? comp.getGraphicsConfiguration() : null, width, height, type) :
createImage(width, height, type);
}
@@ -2016,7 +2037,7 @@ public class UIUtil {
@NotNull Graphics g,
boolean useRetinaCondition,
Consumer<Graphics2D> paintRoutine) {
if (!useRetinaCondition || !isJDKManagedHiDPIScreen((Graphics2D)g) || Registry.is("ide.mac.retina.disableDrawingFix")) {
if (!useRetinaCondition || !isJreHiDPI(((Graphics2D)g).getDeviceConfiguration()) || Registry.is("ide.mac.retina.disableDrawingFix")) {
paintRoutine.consume((Graphics2D)g);
}
else {
@@ -2167,9 +2188,10 @@ public class UIUtil {
public static void drawStringWithHighlighting(Graphics g, String s, int x, int y, Color foreground, Color highlighting) {
g.setColor(highlighting);
boolean isRetina = isJDKManagedHiDPIScreen();
for (float i = x - 1; i <= x + 1; i += isRetina ? 1/JBUI.sysScale() : 1) {
for (float j = y - 1; j <= y + 1; j += isRetina ? 1/JBUI.sysScale() : 1) {
GraphicsConfiguration gc = ((Graphics2D)g).getDeviceConfiguration();
boolean isRetina = isJreHiDPI(gc);
for (float i = x - 1; i <= x + 1; i += isRetina ? 1/JBUI.sysScale(gc) : 1) {
for (float j = y - 1; j <= y + 1; j += isRetina ? 1/JBUI.sysScale(gc) : 1) {
((Graphics2D)g).drawString(s, i, j);
}
}