package com.kartoflane.superluminal2.utils; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.widgets.Display; /** {@link SWT} font related utility methods. */ public class SWTFontUtils { /** Cache: mapping from SWT devices to their monospaced fonts. */ private static final Map<Device, Font> MONOSPACED_FONTS = new HashMap<Device, Font>(); /** Constructor for the {@link SWTFontUtils} class. */ private SWTFontUtils() { // Static class. } /** * Returns the monospaced font for the current display. The font will * automatically be disposed once the display is disposed. * * <p> * This method is thread safe. * </p> * * @return The monospaced font for the current display. * @throws IllegalStateException * If the method is not invoked from a SWT * UI thread. */ public static Font getMonospacedFont() { synchronized (MONOSPACED_FONTS) { // Get current display. Display display = UIUtils.getDisplay(); if (display == null) { String msg = "Must be invoked for a SWT UI thread."; throw new IllegalStateException(msg); } // Forward request. return getMonospacedFont(display); } } /** * Creates a monospaced font for the given display. The font will * automatically be disposed once the display is disposed. * * <p> * This method is thread safe. * </p> * * @param display * The display for which to create a monospaced font. * @return A monospaced font for the given display. */ public static Font getMonospacedFont(final Display display) { synchronized (MONOSPACED_FONTS) { // Based on class 'org.eclipse.jface.resource.FontRegistry' and // resources 'org.eclipse.jface.resource/jfacefonts*.properties' // from 'org.eclipse.jface' plug-in (version 3.9.1). // Use cache if possible. Font cachedFont = MONOSPACED_FONTS.get(display); if (cachedFont != null) return cachedFont; // Get operating system and windowing system names. String os = System.getProperty("os.name"); String ws = SWT.getPlatform(); os = deleteWhitespace(os).toLowerCase(Locale.US); ws = deleteWhitespace(ws).toLowerCase(Locale.US); // Get names to check, in order from specific to generic. String[] names = { os + "_" + ws, os, "" }; // Get font data texts for platform. String[] fontDataTxts = null; for (String name : names) { if (name.equals("aix")) { fontDataTxts = new String[] { "adobe-courier|normal|12" }; break; } else if (name.equals("hp-ux")) { fontDataTxts = new String[] { "adobe-courier|normal|14" }; break; } else if (name.equals("linux_gtk")) { fontDataTxts = new String[] { "Monospace|normal|10" }; break; } else if (name.equals("linux")) { fontDataTxts = new String[] { "adobe-courier|normal|12" }; break; } else if (name.equals("macosx")) { fontDataTxts = new String[] { "Monaco|normal|11", "Courier|normal|12", "Courier New|normal|12" }; break; } else if (name.equals("sunos") || name.equals("solaris")) { fontDataTxts = new String[] { "adobe-courier|normal|12" }; break; } else if (name.equals("windows98")) { fontDataTxts = new String[] { "Courier New|normal|10", "Courier|normal|10", "Lucida Console|normal|9" }; break; } else if (name.equals("windowsnt")) { fontDataTxts = new String[] { "Courier New|normal|10", "Courier|normal|10", "Lucida Console|normal|9" }; break; } else if (name.equals("windows2000")) { fontDataTxts = new String[] { "Courier New|normal|10", "Courier|normal|10", "Lucida Console|normal|9" }; break; } else if (name.equals("windowsxp")) { fontDataTxts = new String[] { "Courier New|normal|10", "Courier|normal|10", "Lucida Console|normal|9" }; break; } else if (name.equals("windowsvista")) { fontDataTxts = new String[] { "Consolas|normal|10", "Courier New|normal|10" }; break; } else if (name.equals("windows7")) { fontDataTxts = new String[] { "Consolas|normal|10", "Courier New|normal|10" }; break; } else if (name.equals("windows8")) { fontDataTxts = new String[] { "Consolas|normal|10", "Courier New|normal|10" }; break; } else if (name.equals("")) { fontDataTxts = new String[] { "Courier New|normal|10", "Courier|normal|10", "b&h-lucidabright|normal|9" }; break; } } if (fontDataTxts == null) { // Can't happen, but silences a warning. throw new AssertionError(); } // Convert texts to font data. FontData[] fontDatas = new FontData[fontDataTxts.length]; for (int i = 0; i < fontDatas.length; i++) { // Find splitters. String txt = fontDataTxts[i]; int bar2 = txt.lastIndexOf('|'); int bar1 = txt.lastIndexOf('|', bar2 - 1); // Get font name. String name = txt.substring(0, bar1); // Get font style. String[] styles = txt.substring(bar1 + 1, bar2).split(","); int style = 0; for (String s : styles) { if (s.equals("normal")) { style |= SWT.NORMAL; } else if (s.equals("bold")) { style |= SWT.BOLD; } else if (s.equals("italic")) { style |= SWT.ITALIC; } else { throw new RuntimeException("Invalid style: " + s); } } // Get font height. int height = Integer.parseInt(txt.substring(bar2 + 1)); // Create and add font date. fontDatas[i] = new FontData(name, height, style); } // Create font. final Font font = new Font(display, fontDatas); // Register dispose callback, to dispose of the font once the // display is disposed. display.disposeExec(new Runnable() { @Override public void run() { synchronized (MONOSPACED_FONTS) { MONOSPACED_FONTS.remove(display); font.dispose(); } } }); // Add to cache. MONOSPACED_FONTS.put(display, font); // Return the new font. return font; } } private static String deleteWhitespace(String string) { return string.replaceAll("\\s", ""); } }