package utils;
import java.awt.AWTKeyStroke;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.swing.JComponent;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import aliview.AliView;
public class OSNativeUtils {
private static final Logger logger = Logger.getLogger(OSNativeUtils.class);
private static float cachedContentScaleFactor = -1; // 1 indicates a regular mac display. 2= retina
public static boolean isWindows() {
String os = System.getProperty("os.name").toLowerCase();
// windows
return (os.indexOf("win") >= 0);
}
public static float getHighDPIScaleFactor() {
if(cachedContentScaleFactor == -1){
Object obj = Toolkit.getDefaultToolkit().getDesktopProperty("apple.awt.contentScaleFactor");
if (obj instanceof Float) {
Float f = (Float) obj;
cachedContentScaleFactor = f;
}else{
cachedContentScaleFactor = 1;
}
}
return cachedContentScaleFactor;
}
public static boolean isRunningDefectJFilechooserJVM(){
logger.info("java ver" + getJavaVersionAsDouble());
String javaVersion = System.getProperty("java.version").toLowerCase();
if(isWindows() && getJavaVersionAsDouble() >= 7){
return true;
}
return false;
}
/*
*
* 1.6.0_25 is returned as 6.25
*
*/
private static double getJavaVersionAsDouble(){
double version = 0;
try{
// java version "";
String javaVersion = System.getProperty("java.version").toLowerCase();
String[] splitted = StringUtils.split(javaVersion,"._-");
String major = splitted[1];
String minor = splitted[3];
String versionString = major + "." + minor;
version = Double.parseDouble(versionString);
}catch(Exception e){
e.printStackTrace();
}
return version;
}
public static boolean isMac() {
String os = System.getProperty("os.name").toLowerCase();
// Mac
return (os.indexOf("mac") >= 0);
}
public static boolean isAnythingButMac() {
return ! isMac();
}
public static boolean isLinuxOrUnix() {
String os = System.getProperty("os.name").toLowerCase();
// linux or unix
return (os.indexOf("nix") >= 0 || os.indexOf("nux") >= 0);
}
public static boolean isSolaris() {
String os = System.getProperty("os.name").toLowerCase();
// Solaris
return (os.indexOf("sunos") >= 0);
}
public static boolean is32BitOS() {
String os = System.getProperty("os.arch").toLowerCase();
return (os.indexOf("32") >= 0);
}
public static boolean is64BitOS() {
String os = System.getProperty("os.arch").toLowerCase();
return (os.indexOf("64") >= 0);
}
public static boolean isPowerPC() {
String os = System.getProperty("os.arch").toLowerCase();
return (os.indexOf("powerpc") >= 0);
}
public static KeyStroke getReloadKeyAccelerator() {
return KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK);
}
public static KeyStroke getCopySelectionAsFastaKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getCopyKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.META_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}
}
public static int getMouseWheelZoomModifierMask() {
if(isMac()){
return InputEvent.META_DOWN_MASK;
}else{
return InputEvent.CTRL_DOWN_MASK;
}
}
/*
public static KeyStroke getDecreaseFontSizeKeyAccelerator() {
return KeyStroke.getKeyStroke('-');
}
public static KeyStroke getIncreaseFontSizeKeyAccelerator() {
return KeyStroke.getKeyStroke('+');
}
*/
public static KeyStroke getPasteKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getIncreaseFontSizeKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke('+');//, InputEvent.META_DOWN_MASK); // Command and + is not working on mac
}else{
return KeyStroke.getKeyStroke('+');//, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getDecreaseFontSizeKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke('-');//, InputEvent.META_DOWN_MASK); // Command and - is not working on mac
}else{
return KeyStroke.getKeyStroke('-');//, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getClearKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
}
}
public static KeyStroke getDeleteKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getUndoKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_Z, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getRedoKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getMoveSelectionUpKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getMoveSelectionDownKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getMoveSelectedRightKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getMoveSelectedLeftKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getInsertGapMoveRightKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE,0);
}
}
public static KeyStroke getInsertGapMoveLeftKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke getDeleteGapMoveLeftKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE,0);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE,0);
}
}
public static KeyStroke getDeleteGapMoveRightKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke getToggleTranslationKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getToggleIgnoreGapInTranslationKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.META_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}
}
public static KeyStroke getSelectAllKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getSelectionExpandRightKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke getSelectionExpandLeftKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke getToggleTranslationOnePosKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.META_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke getToggleTranslateShowBothKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.ALT_DOWN_MASK);
}
}
public static KeyStroke getToggleTranslateShowAACodeKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_T, InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}
}
public static KeyStroke incReadingFrameKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke getExpandSelectionDownKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke decReadingFrameKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.SHIFT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.SHIFT_DOWN_MASK);
}
}
public static KeyStroke countStopCodonsKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.META_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
}
}
public static KeyStroke getAddOrRemoveExcludesKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getSaveFileAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getOpenFileAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getNewFileAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getPrintAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK);
}
}
public static String getStandardCommandModifierKeyName() {
if(isMac()){
return "⌘";
}else{
return "Ctrl";
}
}
public static KeyStroke getRenameKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0);
}
}
public static KeyStroke getCloseWinKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_W, InputEvent.CTRL_DOWN_MASK);
}
}
public static KeyStroke getFocusNextWinKeyAccelerator() {
if(isMac()){
return KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.META_DOWN_MASK);
}else{
return KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.CTRL_DOWN_MASK);
}
}
/**
* Swing menus are looking pretty bad on Linux when the GTK LaF is used (See
* bug #6925412). It will most likely never be fixed anytime soon so this
* method provides a workaround for it. It uses reflection to change the GTK
* style objects of Swing so popup menu borders have a minimum thickness of
* 1 and menu separators have a minimum vertical thickness of 1.
*/
public static final void installGtkPopupBugWorkaround()
{
// Get current look-and-feel implementation class
LookAndFeel laf = UIManager.getLookAndFeel();
Class<?> lafClass = laf.getClass();
// Do nothing when not using the problematic LaF
if (!lafClass.getName().equals(
"com.sun.java.swing.plaf.gtk.GTKLookAndFeel")) return;
// We do reflection from here on. Failure is silently ignored. The
// workaround is simply not installed when something goes wrong here
try
{
// Access the GTK style factory
Field field = lafClass.getDeclaredField("styleFactory");
boolean accessible = field.isAccessible();
field.setAccessible(true);
Object styleFactory = field.get(laf);
field.setAccessible(accessible);
// Fix the horizontal and vertical thickness of popup menu style
Object style = getGtkStyle(styleFactory, new JPopupMenu(),
"POPUP_MENU");
fixGtkThickness(style, "yThickness");
fixGtkThickness(style, "xThickness");
// Fix the vertical thickness of the popup menu separator style
style = getGtkStyle(styleFactory, new JSeparator(),
"POPUP_MENU_SEPARATOR");
fixGtkThickness(style, "yThickness");
}
catch (Exception e)
{
// Silently ignored. Workaround can't be applied.
}
}
/**
* Called internally by installGtkPopupBugWorkaround to fix the thickness
* of a GTK style field by setting it to a minimum value of 1.
*
* @param style
* The GTK style object.
* @param fieldName
* The field name.
* @throws Exception
* When reflection fails.
*/
private static void fixGtkThickness(Object style, String fieldName)
throws Exception
{
Field field = style.getClass().getDeclaredField(fieldName);
boolean accessible = field.isAccessible();
field.setAccessible(true);
field.setInt(style, Math.max(1, field.getInt(style)));
field.setAccessible(accessible);
}
/**
* Called internally by installGtkPopupBugWorkaround. Returns a specific
* GTK style object.
*
* @param styleFactory
* The GTK style factory.
* @param component
* The target component of the style.
* @param regionName
* The name of the target region of the style.
* @return The GTK style.
* @throws Exception
* When reflection fails.
*/
private static Object getGtkStyle(Object styleFactory,
JComponent component, String regionName) throws Exception
{
// Create the region object
Class<?> regionClass = Class.forName("javax.swing.plaf.synth.Region");
Field field = regionClass.getField(regionName);
Object region = field.get(regionClass);
// Get and return the style
Class<?> styleFactoryClass = styleFactory.getClass();
Method method = styleFactoryClass.getMethod("getStyle",
new Class<?>[] { JComponent.class, regionClass });
boolean accessible = method.isAccessible();
method.setAccessible(true);
Object style = method.invoke(styleFactory, component, region);
method.setAccessible(accessible);
return style;
}
/*
*
* Register through reflection and other OS wont be affected
*
*/
public static boolean registerMacAdapter(AliView aliView) {
boolean registerOK = false;
if(isMac()){
logger.info("register Mac Adapter");
try {
Class macAdapter = Class.forName("utils.MacAdapter");
if(macAdapter != null){
Class[] defArgs = {AliView.class};
Method regAppMethod = macAdapter.getDeclaredMethod("registerApplication", defArgs);
if(regAppMethod != null){
Object[] args = {aliView};
regAppMethod.invoke(macAdapter, args);
registerOK = true;
}
}
} catch (Exception e) {
e.printStackTrace();
} catch (Error err){
err.printStackTrace();
}
}
return registerOK;
}
}