From: Jim Procter Date: Wed, 15 Jun 2022 14:41:53 +0000 (+0100) Subject: Merge branch 'improvement/JAL-1988+JAL-3416_Java8_macOS_APQHandlers_and_FlatLaF_optio... X-Git-Tag: Release_2_11_2_6~49 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=21acae0b82847edffad1339a1e3ad5f39bf8c661;hp=135c826c69042c04c64cb8df30fdaef92eeb4ffc;p=jalview.git Merge branch 'improvement/JAL-1988+JAL-3416_Java8_macOS_APQHandlers_and_FlatLaF_option' into develop --- diff --git a/j11lib/flatlaf-2.3.jar b/j11lib/flatlaf-2.3.jar new file mode 100644 index 0000000..9f292d2 Binary files /dev/null and b/j11lib/flatlaf-2.3.jar differ diff --git a/j11lib/flatlaf-extras-2.3.jar b/j11lib/flatlaf-extras-2.3.jar new file mode 100644 index 0000000..39e9701 Binary files /dev/null and b/j11lib/flatlaf-extras-2.3.jar differ diff --git a/j8lib/flatlaf-2.3.jar b/j8lib/flatlaf-2.3.jar new file mode 100644 index 0000000..9f292d2 Binary files /dev/null and b/j8lib/flatlaf-2.3.jar differ diff --git a/j8lib/flatlaf-extras-2.3.jar b/j8lib/flatlaf-extras-2.3.jar new file mode 100644 index 0000000..39e9701 Binary files /dev/null and b/j8lib/flatlaf-extras-2.3.jar differ diff --git a/src/jalview/bin/Jalview.java b/src/jalview/bin/Jalview.java index fc4c821..fd1783a 100755 --- a/src/jalview/bin/Jalview.java +++ b/src/jalview/bin/Jalview.java @@ -20,6 +20,7 @@ */ package jalview.bin; +import java.awt.Color; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; @@ -44,9 +45,12 @@ import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UIManager.LookAndFeelInfo; +import com.formdev.flatlaf.FlatLightLaf; +import com.formdev.flatlaf.util.SystemInfo; import com.threerings.getdown.util.LaunchUtil; //import edu.stanford.ejalbert.launching.IBrowserLaunching; @@ -862,8 +866,8 @@ public class Jalview private static void setLookAndFeel() { - // property laf = "crossplatform", "system", "gtk", "metal", "nimbus" or - // "mac" + // property laf = "crossplatform", "system", "gtk", "metal", "nimbus", + // "mac" or "flat" // If not set (or chosen laf fails), use the normal SystemLaF and if on Mac, // try Quaqua/Vaqua. String lafProp = System.getProperty("laf"); @@ -915,6 +919,13 @@ public class Jalview Console.error("Could not set requested laf=" + laf); } break; + case "flat": + lafSet = setFlatLookAndFeel(); + if (!lafSet) + { + Console.error("Could not set requested laf=" + laf); + } + break; case "quaqua": lafSet = setQuaquaLookAndFeel(); if (!lafSet) @@ -1035,6 +1046,45 @@ public class Jalview "javax.swing.plaf.nimbus.NimbusLookAndFeel", false); } + private static boolean setFlatLookAndFeel() + { + boolean set = setSpecificLookAndFeel("flatlaf light", + "com.formdev.flatlaf.FlatLightLaf", false); + if (set) + { + if (Platform.isMac()) + { + System.setProperty("apple.laf.useScreenMenuBar", "true"); + System.setProperty("apple.awt.application.name", + ChannelProperties.getProperty("app_name")); + System.setProperty("apple.awt.application.appearance", "system"); + if (SystemInfo.isMacFullWindowContentSupported + && Desktop.desktop != null) + { + Desktop.desktop.getRootPane() + .putClientProperty("apple.awt.fullWindowContent", true); + Desktop.desktop.getRootPane() + .putClientProperty("apple.awt.transparentTitleBar", true); + } + + SwingUtilities.invokeLater(() -> { + FlatLightLaf.setup(); + }); + } + + UIManager.put("TabbedPane.showTabSeparators", true); + UIManager.put("TabbedPane.tabSeparatorsFullHeight", true); + UIManager.put("TabbedPane.tabsOverlapBorder", true); + // UIManager.put("TabbedPane.hasFullBorder", true); + UIManager.put("TabbedPane.tabLayoutPolicy", "scroll"); + UIManager.put("TabbedPane.scrollButtonsPolicy", "asNeeded"); + UIManager.put("TabbedPane.smoothScrolling", true); + UIManager.put("TabbedPane.tabWidthMode", "compact"); + UIManager.put("TabbedPane.selectedBackground", Color.white); + } + return set; + } + private static boolean setQuaquaLookAndFeel() { return setSpecificLookAndFeel("quaqua", diff --git a/src/jalview/gui/APQHandlers.java b/src/jalview/gui/APQHandlers.java deleted file mode 100644 index e5e328f..0000000 --- a/src/jalview/gui/APQHandlers.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) - * Copyright (C) $$Year-Rel$$ The Jalview Authors - * - * This file is part of Jalview. - * - * Jalview is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 - * of the License, or (at your option) any later version. - * - * Jalview is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Jalview. If not, see . - * The Jalview Authors are detailed in the 'AUTHORS' file. - */ -package jalview.gui; - -import jalview.bin.Cache; -import jalview.util.MessageManager; -import jalview.util.Platform; - -import java.awt.Desktop; -import java.awt.desktop.AboutEvent; -import java.awt.desktop.AboutHandler; -import java.awt.desktop.PreferencesEvent; -import java.awt.desktop.PreferencesHandler; -import java.awt.desktop.QuitEvent; -import java.awt.desktop.QuitHandler; -import java.awt.desktop.QuitResponse; -import java.awt.desktop.QuitStrategy; - -import javax.swing.JOptionPane; - -public class APQHandlers -{ - private static boolean setAPQHandlers = false; - - public APQHandlers() - { - } - - protected static boolean setAPQHandlers( - jalview.gui.Desktop jalviewDesktop) - { - // flagging this test to avoid unnecessary reflection - if (!setAPQHandlers) - { - // see if the Quit, About and Preferences handlers are available - Class desktopClass = Desktop.class; - Desktop hdesktop = Desktop.getDesktop(); - - try - { - Float specversion = Float.parseFloat( - System.getProperty("java.specification.version")); - - if (specversion >= 9) - { - if (Platform.isAMacAndNotJS()) - { - if (desktopClass.getDeclaredMethod("setAboutHandler", - new Class[] - { AboutHandler.class }) != null) - { - - hdesktop.setAboutHandler(new AboutHandler() - { - @Override - public void handleAbout(AboutEvent e) - { - jalviewDesktop.aboutMenuItem_actionPerformed(null); - } - }); - - } - - if (desktopClass.getDeclaredMethod("setPreferencesHandler", - new Class[] - { PreferencesHandler.class }) != null) - { - - hdesktop.setPreferencesHandler(new PreferencesHandler() - { - @Override - public void handlePreferences(PreferencesEvent e) - { - jalviewDesktop.preferences_actionPerformed(null); - } - }); - - } - - if (desktopClass.getDeclaredMethod("setQuitHandler", - new Class[] - { QuitHandler.class }) != null) - { - - hdesktop.setQuitHandler(new QuitHandler() - { - @Override - public void handleQuitRequestWith(QuitEvent e, - QuitResponse r) - { - boolean confirmQuit = Cache.getDefault( - jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT, true); - int n; - if (confirmQuit) - { - n = JOptionPane.showConfirmDialog(null, - MessageManager.getString("label.quit_jalview"), - MessageManager.getString("action.quit"), - JOptionPane.OK_CANCEL_OPTION, - JOptionPane.PLAIN_MESSAGE, null); - } - else - { - n = JOptionPane.OK_OPTION; - } - if (n == JOptionPane.OK_OPTION) - { - System.out.println("Shortcut Quit confirmed by user"); - jalviewDesktop.quit(); - r.performQuit(); // probably won't reach this line, but just - // in - // case - } - else - { - r.cancelQuit(); - System.out.println("Shortcut Quit cancelled by user"); - } - } - }); - hdesktop.setQuitStrategy(QuitStrategy.CLOSE_ALL_WINDOWS); - - } - } - setAPQHandlers = true; - } - else - { - System.out.println( - "Not going to try setting APQ Handlers as java.spec.version is " - + specversion); - } - - } catch (Exception e) - { - System.out.println( - "Exception when looking for About, Preferences, Quit Handlers"); - // e.printStackTrace(); - } catch (Throwable t) - { - System.out.println( - "Throwable when looking for About, Preferences, Quit Handlers"); - // t.printStackTrace(); - } - - } - - return setAPQHandlers; - } - -} diff --git a/src/jalview/gui/Desktop.java b/src/jalview/gui/Desktop.java index aeb0fac..3ad5384 100644 --- a/src/jalview/gui/Desktop.java +++ b/src/jalview/gui/Desktop.java @@ -20,8 +20,6 @@ */ package jalview.gui; -import java.util.Locale; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -64,6 +62,7 @@ import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.ListIterator; +import java.util.Locale; import java.util.Vector; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -183,7 +182,7 @@ public class Desktop extends jalview.jbgui.GDesktop private static final String EXPERIMENTAL_FEATURES = "EXPERIMENTAL_FEATURES"; - protected static final String CONFIRM_KEYBOARD_QUIT = "CONFIRM_KEYBOARD_QUIT"; + public static final String CONFIRM_KEYBOARD_QUIT = "CONFIRM_KEYBOARD_QUIT"; public static HashMap savingFiles = new HashMap(); @@ -444,24 +443,6 @@ public class Desktop extends jalview.jbgui.GDesktop } } - /** - * APQHandlers sets handlers for About, Preferences and Quit actions - * peculiar to macOS's application menu. APQHandlers will check to see if a - * handler is supported before setting it. - */ - try - { - APQHandlers.setAPQHandlers(this); - } catch (Exception e) - { - System.out.println("Cannot set APQHandlers"); - // e.printStackTrace(); - } catch (Throwable t) - { - jalview.bin.Console - .warn("Error setting APQHandlers: " + t.toString()); - jalview.bin.Console.trace(Cache.getStackTraceString(t)); - } setIconImages(ChannelProperties.getIconList()); addWindowListener(new WindowAdapter() diff --git a/src/jalview/jbgui/APQHandlers.java b/src/jalview/jbgui/APQHandlers.java new file mode 100644 index 0000000..e18ec44 --- /dev/null +++ b/src/jalview/jbgui/APQHandlers.java @@ -0,0 +1,90 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +package jalview.jbgui; + +import javax.swing.JFrame; +import javax.swing.JOptionPane; + +import com.formdev.flatlaf.extras.FlatDesktop; + +import jalview.util.MessageManager; + +public class APQHandlers +{ + protected static boolean setAPQHandlers = false; + + public static boolean setAPQHandlers(GDesktop desktop) + { + FlatDesktop.setAboutHandler(() -> { + desktop.aboutMenuItem_actionPerformed(null); + }); + FlatDesktop.setPreferencesHandler(() -> { + desktop.preferences_actionPerformed(null); + }); + FlatDesktop.setQuitHandler(response -> { + boolean confirmQuit = jalview.bin.Cache + .getDefault(jalview.gui.Desktop.CONFIRM_KEYBOARD_QUIT, true); + boolean canQuit = !confirmQuit; + int n; + if (confirmQuit) + { + // ensure Jalview window is brought to front for Quit confirmation + // window to be + // visible + + // this method of raising the Jalview window is broken in java + // jalviewDesktop.setVisible(true); + // jalviewDesktop.toFront(); + + // a better hack which works instead + JFrame dialogParent = new JFrame(); + dialogParent.setAlwaysOnTop(true); + + n = JOptionPane.showConfirmDialog(dialogParent, + MessageManager.getString("label.quit_jalview"), + MessageManager.getString("action.quit"), + JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, + null); + + dialogParent.setAlwaysOnTop(false); + dialogParent.dispose(); + } + else + { + n = JOptionPane.OK_OPTION; + } + canQuit = (n == JOptionPane.OK_OPTION); + if (canQuit) + { + response.performQuit(); + } + else + { + response.cancelQuit(); + } + }); + + setAPQHandlers = true; + + return setAPQHandlers; + } + +} diff --git a/src/jalview/jbgui/GDesktop.java b/src/jalview/jbgui/GDesktop.java index e1224c2..f3d9a65 100755 --- a/src/jalview/jbgui/GDesktop.java +++ b/src/jalview/jbgui/GDesktop.java @@ -20,11 +20,6 @@ */ package jalview.jbgui; -import jalview.api.AlignmentViewPanel; -import jalview.io.FileFormatException; -import jalview.util.MessageManager; -import jalview.util.Platform; - import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -35,6 +30,12 @@ import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; +import jalview.api.AlignmentViewPanel; +import jalview.bin.Cache; +import jalview.io.FileFormatException; +import jalview.util.MessageManager; +import jalview.util.Platform; + /** * DOCUMENT ME! * @@ -139,6 +140,25 @@ public class GDesktop extends JFrame */ private void jbInit() throws Exception { + /** + * APQHandlers sets handlers for About, Preferences and Quit actions + * peculiar to macOS's application menu. APQHandlers will check to see if a + * handler is supported before setting it. + */ + try + { + APQHandlers.setAPQHandlers(this); + } catch (Exception e) + { + System.out.println("Cannot set APQHandlers"); + // e.printStackTrace(); + } catch (Throwable t) + { + jalview.bin.Console + .warn("Error setting APQHandlers: " + t.toString()); + jalview.bin.Console.trace(Cache.getStackTraceString(t)); + } + setName("jalview-desktop"); FileMenu.setText(MessageManager.getString("action.file")); HelpMenu.setText(MessageManager.getString("action.help")); @@ -385,9 +405,12 @@ public class GDesktop extends JFrame FileMenu.add(loadState); FileMenu.addSeparator(); FileMenu.add(quit); - HelpMenu.add(aboutMenuItem); + if (!APQHandlers.setAPQHandlers) + { + HelpMenu.add(aboutMenuItem); + } HelpMenu.add(documentationMenuItem); - if (!Platform.isAMacAndNotJS() || specversion < 11) + if (!APQHandlers.setAPQHandlers) { toolsMenu.add(preferences); }