com.actelion.research.gui.hidpi.HiDPIHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
package com.actelion.research.gui.hidpi;
import com.actelion.research.gui.LookAndFeelHelper;
import com.actelion.research.util.ColorHelper;
import com.actelion.research.util.Platform;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URL;
public class HiDPIHelper {
private static final int COLOR1_BRIGHT_LAF = 0x00503CB4; // main button color in supplied images
private static final int COLOR2_BRIGHT_LAF = 0x00000000; // second button color in supplied images
private static final int COLOR1_DARK_LAF = 0x00B4A0FF; // main button color in supplied images
private static final int COLOR2_DARK_LAF = 0x00E0E0E0; // second button color in supplied images
private static final float ICON_SCALE_LIMIT = 1.2f; // custom dpi scale factors smaller than this will be neglected
// This is an Apple only solution and needs to be adapted to support high-res displays of other vendors
private static float sRetinaFactor = -1f;
private static float sUIScaleFactor = -1f;
/**
* Macintosh retina display support for Java 7 and newer.
*
* @return 1.0 on standard resolution devices and 2.0 for retina screens
*/
public static float getRetinaScaleFactor() {
/* with Apple-Java-6 this was:
Object sContentScaleFactorObject = Toolkit.getDefaultToolkit().getDesktopProperty("apple.awt.contentScaleFactor");
private static final float sRetinaFactor = (sContentScaleFactorObject == null) ? 1f : ((Float)sContentScaleFactorObject).floatValue();
*/
if (sRetinaFactor != -1f)
return sRetinaFactor;
sRetinaFactor = 1f;
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice device = env.getDefaultScreenDevice();
try {
Field field = device.getClass().getDeclaredField("scale");
if (field != null) {
field.setAccessible(true);
Object scale = field.get(device);
if (scale instanceof Integer)
sRetinaFactor = (Integer) scale;
else
System.out.println("Unexpected content scale (not 1 nor 2): "+scale.toString());
}
}
catch (Throwable e) {}
return sRetinaFactor;
}
/**
* For Windows and Linux this method returns the user defined UI scaling factor.
* On Windows this is done by judging by the size of the UIManager's Label.font
* and comparing it to the unscaled default (13). Typically this factor is larger
* than 1.0 on HiDPI devices. For this method to work the Look&Feel must consider
* the OS provided setting and scale its fonts accordingly.
* If a Java system property 'dpifactor' is defined, its value is used rather than
* a font size derived one.
* On the Macintosh this factor is usually 1.0, because HiDPI device support uses
* a diffewrent mechanism (see getRetinaScaleFactor()).
* @return typically 1.0 or 1.25, 1.5, ...
*/
public static float getUIScaleFactor() {
if (sUIScaleFactor == -1) {
sUIScaleFactor = Platform.isWindows() ? (float) UIManager.getFont("Label.font").getSize() / 13f : 1f;
if (System.getProperty("dpifactor") != null) {
try {
sUIScaleFactor = Float.parseFloat(System.getProperty("dpifactor"));
}
catch (NumberFormatException nfe) {}
}
}
return sUIScaleFactor;
}
/**
* This is a convenience method that scales the passed int value with getUIScaleFactor()
* and returns the rounded result.
* @param value
* @return
*/
public static int scale(int value) {
return Math.round(getUIScaleFactor() * value);
}
/**
* This is a convenience method that scales the passed int value with getUIScaleFactor()
* and with getRetinaScaleFactor() and returns the rounded result.
* @param value
* @return
*/
public static int scaleRetinaAndUI(int value) {
return Math.round(getUIScaleFactor() * getRetinaScaleFactor() * value);
}
public static Icon createIcon(String fileName, int rotation) {
return new HiDPIIcon(scale(rotate(createLaFCompatibleImage(fileName), rotation)));
}
public static Icon createDisabledIcon(String fileName, int rotation) {
return new HiDPIIcon(scale(rotate(createDisabledImage(fileName), rotation)));
}
private static String getDoubleResolutionFileName(String fileName) {
int index = fileName.lastIndexOf('.');
return fileName.substring(0, index).concat("@2x").concat(fileName.substring(index));
}
private static BufferedImage rotate(BufferedImage image, int rotation) {
int size = image.getHeight();
int max = size-1;
if (rotation == 90) {
for (int x=0; x ICON_SCALE_LIMIT)
fileName = getDoubleResolutionFileName(fileName);
URL url = HiDPIIconButton.class.getResource("/images/" + fileName);
if (url == null)
throw new RuntimeException("Could not find: " + fileName);
try {
BufferedImage image = ImageIO.read(url);
return image;
}
catch (IOException ioe) { return null; }
}
/**
* Creates an image from the fileName. On HiDPI devices this is a high
* resolution image. If the current look&feel is dark, then colors are adapted
* for optimal contrast.
* @param fileName
* @return
*/
public static BufferedImage createLaFCompatibleImage(String fileName) {
BufferedImage image = createImage(fileName);
if (image != null && LookAndFeelHelper.isDarkLookAndFeel())
brightenImage(image);
return image;
}
private static BufferedImage createDisabledImage(String fileName) {
BufferedImage image = createLaFCompatibleImage(fileName);
Color gray = LookAndFeelHelper.isDarkLookAndFeel() ?
ColorHelper.brighter(UIManager.getColor("Panel.background"), 0.8f)
: ColorHelper.darker(UIManager.getColor("Panel.background"), 0.8f);
int grayRGB = 0x00FFFFFF & gray.getRGB();
for (int x=0; x ICON_SCALE_LIMIT) // in this case we have double size images
return image.getScaledInstance(Math.round(0.5f * scale * image.getWidth()),
Math.round(0.5f * scale * image.getHeight()), Image.SCALE_SMOOTH);
else
return image;
}
private static void brightenImage(BufferedImage image) {
for (int x=0; x
© 2015 - 2025 Weber Informatics LLC | Privacy Policy