OSDN Git Service

OSX上のJDK9で実行する場合にスクリーンメニューのabout, preferences, quitのメニューが効かなくなっていた問題の修正
authorseraphy <seraphy@users.osdn.me>
Sun, 25 Feb 2018 15:35:31 +0000 (00:35 +0900)
committerseraphy <seraphy@users.osdn.me>
Sun, 25 Feb 2018 15:35:31 +0000 (00:35 +0900)
pom.xml
src/main/java/charactermanaj/Main.java
src/main/java/charactermanaj/ui/MainFrame.java
src/main/java/charactermanaj/ui/MainFramePartialForMacOSX9.java [new file with mode: 0644]
src/main/java/charactermanaj/ui/util/SpinnerWheelSupportListener.java

diff --git a/pom.xml b/pom.xml
index 76f4752..740193f 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 \r
        <groupId>jp.seraphyware.charactermanaj</groupId>\r
        <artifactId>CharacterManaJ</artifactId>\r
-       <version>0.9.9.8</version>\r
+       <version>0.9.9.9</version>\r
 \r
        <url>https://osdn.net/projects/charactermanaj/</url>\r
 \r
                <buildBy>seraphy@users.osdn.me</buildBy>\r
                <mainClass>charactermanaj.CharacterManaJ</mainClass>\r
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r
-               <maven.compiler.source>1.5</maven.compiler.source>\r
-               <maven.compiler.target>1.5</maven.compiler.target>\r
-               <animalSnifferArtifact>java15</animalSnifferArtifact>\r
-               <animalSnifferArtifactVersion>1.0</animalSnifferArtifactVersion>\r
+               <maven.compiler.source>1.6</maven.compiler.source>\r
+               <maven.compiler.target>1.6</maven.compiler.target>\r
+               <animalSnifferArtifact>java16</animalSnifferArtifact>\r
+               <animalSnifferArtifactVersion>1.1</animalSnifferArtifactVersion>\r
                <maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>\r
        </properties>\r
 \r
index 4102f4d..44125ef 100644 (file)
@@ -24,6 +24,7 @@ import charactermanaj.graphics.io.ImageCacheMBeanImpl;
 import charactermanaj.model.AppConfig;
 import charactermanaj.model.util.StartupSupport;
 import charactermanaj.ui.MainFrame;
+import charactermanaj.ui.MainFramePartialForMacOSX9;
 import charactermanaj.ui.ProfileListManager;
 import charactermanaj.ui.SelectCharatersDirDialog;
 import charactermanaj.util.AWTExceptionLoggingHandler;
@@ -36,7 +37,7 @@ import charactermanaj.util.LocalizedResourcePropertyLoader;
 
 /**
  * エントリポイント用クラス
- * 
+ *
  * @author seraphy
  */
 public final class Main implements Runnable {
@@ -119,7 +120,7 @@ public final class Main implements Runnable {
 
        /**
         * UIをセットアップする.
-        * 
+        *
         * @throws Exception
         *             いろいろな失敗
         */
@@ -150,7 +151,7 @@ public final class Main implements Runnable {
                // 優先するフォントファミリ中の実在するフォントファミリのセット(大文字小文字の区別なし)
                TreeSet<String> availablePriorityFontSets = new TreeSet<String>(
                                String.CASE_INSENSITIVE_ORDER);
-               
+
                // 少なくともメニューが表示できるようなフォントを選択する
                Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
                                .getLocalizedProperties("menu/menu");
@@ -206,7 +207,7 @@ public final class Main implements Runnable {
                                selectedFontFamily = "Dialog";
                        }
                }
-               
+
                // デフォルトのフォントサイズ、0以下の場合はシステム標準のまま
                int defFontSize = appConfig.getDefaultFontSize();
 
@@ -221,7 +222,7 @@ public final class Main implements Runnable {
                                FontUIResource fontUIResource = (FontUIResource) val;
                                int fontSize = fontUIResource.getSize();
                                String fontFamily = fontUIResource.getFamily();
-                               
+
                                if (defFontSize > 0) {
                                        fontSize = defFontSize;
                                }
@@ -236,7 +237,7 @@ public final class Main implements Runnable {
                                        }
                                        fontFamily = selectedFontFamily;
                                }
-                               
+
                                fontUIResource = new FontUIResource(fontFamily,
                                                fontUIResource.getStyle(), fontSize);
                                UIManager.put(entry.getKey(), fontUIResource);
@@ -321,22 +322,28 @@ public final class Main implements Runnable {
 
                        // デフォルトのプロファイルを開く.
                        // (最後に使ったプロファイルがあれば、それが開かれる.)
-                       MainFrame mainFrame = ProfileListManager.openDefaultProfile();
+                       final MainFrame mainFrame = ProfileListManager.openDefaultProfile();
                        if (isMacOSX()) {
                                try {
-                                       // MacOSXであればスクリーンメニューからのイベントをハンドルできるようにする.
-                                       // OSXにしか存在しないクラスを利用するためリフレクションとしている.
-                                       // ただしJDKによっては、Apple Java Extensionsがないことも予想されるので、
-                                       // その場合はエラーにしない。
-                                       Class<?> clz = Class
-                                                       .forName("charactermanaj.ui.MainFramePartialForMacOSX");
-                                       Method mtd = clz.getMethod("setupScreenMenu",
-                                                       MainFrame.class);
-                                       mtd.invoke(null, mainFrame);
+                                       if (JavaVersionUtils.getJavaVersion() >= 9) {
+                                               // OSXでJava9以降であればOracle実装でスクリーンメニュー類を設定する.
+                                               MainFramePartialForMacOSX9.setupScreenMenu(mainFrame);
+
+                                       } else {
+                                               // Java9未満であればeawtでスクリーンメニュー類を設定する.
+                                               // MacOSXであればスクリーンメニューからのイベントをハンドルできるようにする.
+                                               // OSXにしか存在しないクラスを利用するためリフレクションとしている.
+                                               // ただしJDKによっては、Apple Java Extensionsがないことも予想されるので、
+                                               // その場合はエラーにしない。
+                                               Class<?> clz = Class
+                                                               .forName("charactermanaj.ui.MainFramePartialForMacOSX");
+                                               Method mtd = clz.getMethod("setupScreenMenu",
+                                                               MainFrame.class);
+                                               mtd.invoke(null, mainFrame);
+                                       }
 
                                } catch (Throwable ex) {
-                                       logger.log(Level.CONFIG,
-                                                       "The Apple Java Extensions is not found.", ex);
+                                       logger.log(Level.CONFIG, "Failed to setup the screen menu.", ex);
                                }
                        }
 
@@ -358,7 +365,7 @@ public final class Main implements Runnable {
        /**
         * エントリポイント.<br>
         * 最初のメインフレームを開いたときにMac OS Xであればスクリーンメニューの登録も行う.<br>
-        * 
+        *
         * @param args
         *            引数(未使用)
         */
@@ -381,7 +388,7 @@ public final class Main implements Runnable {
 
        /**
         * Mac OS Xで動作しているか?
-        * 
+        *
         * @return Max OS X上であればtrue
         */
        public static boolean isMacOSX() {
@@ -390,7 +397,7 @@ public final class Main implements Runnable {
 
        /**
         * Mac OS X、もしくはlinuxで動作しているか?
-        * 
+        *
         * @return Mac OS X、もしくはlinuxで動作していればtrue
         */
        public static boolean isLinuxOrMacOSX() {
index f538392..2223dc9 100644 (file)
@@ -1,7 +1,6 @@
 package charactermanaj.ui;\r
 \r
-import static java.lang.Math.max;\r
-import static java.lang.Math.min;\r
+import static java.lang.Math.*;\r
 \r
 import java.awt.BorderLayout;\r
 import java.awt.Color;\r
@@ -1765,7 +1764,7 @@ public class MainFrame extends JFrame
        /**\r
         * アプリケーションの設定ダイアログを開く\r
         */\r
-       protected void onPreferences() {\r
+       public void onPreferences() {\r
                AppConfigDialog appConfigDlg = new AppConfigDialog(this);\r
                appConfigDlg.setVisible(true);\r
        }\r
@@ -2110,7 +2109,7 @@ public class MainFrame extends JFrame
        }\r
 \r
 \r
-       protected void onAbout() {\r
+       public void onAbout() {\r
                try {\r
                        AboutBox aboutBox = new AboutBox(this);\r
                        aboutBox.showAboutBox();\r
diff --git a/src/main/java/charactermanaj/ui/MainFramePartialForMacOSX9.java b/src/main/java/charactermanaj/ui/MainFramePartialForMacOSX9.java
new file mode 100644 (file)
index 0000000..e20b9e4
--- /dev/null
@@ -0,0 +1,87 @@
+package charactermanaj.ui;\r
+\r
+import java.awt.Desktop;\r
+import java.awt.Image;\r
+import java.lang.reflect.InvocationHandler;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Proxy;\r
+import java.util.logging.Logger;\r
+\r
+import javax.imageio.ImageIO;\r
+\r
+import charactermanaj.Main;\r
+\r
+/**\r
+ * Mac OS X用のOracle JDK9以降のメインフレームサポートクラス.<br>\r
+ * スクリーンメニューのハンドラなどを接続している.<br>\r
+ *\r
+ * JDK9以降はAppleのeawtがなくなってOracleのAPIを使う必要があるため.<br>\r
+ * @author seraphy\r
+ */\r
+public class MainFramePartialForMacOSX9 {\r
+\r
+       /**\r
+        * ロガー\r
+        */\r
+       private static final Logger logger = Logger.getLogger(MainFramePartialForMacOSX.class.getName());\r
+\r
+       private MainFramePartialForMacOSX9() {\r
+               super();\r
+       }\r
+\r
+       public static void setupScreenMenu(final MainFrame mainFrame) throws Exception {\r
+               // Java9以降であればOracle実装でスクリーンメニュー類を設定する.\r
+               // (jdk5でコンパイルする都合上、無理矢理リフレクション経由のDynamicProxyでハンドラを作っている)\r
+\r
+               Class<?> taskbarCls = Class.forName("java.awt.Taskbar");\r
+               Object taskbar = taskbarCls.getMethod("getTaskbar").invoke(null);\r
+               Method setIconImageMethod = taskbarCls.getMethod("setIconImage", Image.class);\r
+               Image icon = ImageIO.read(Main.class.getResource("/icons/icon.png"));\r
+               setIconImageMethod.invoke(taskbar, icon);\r
+\r
+               Desktop desktop = Desktop.getDesktop();\r
+               Class<?> aboutHandlerCls = Class.forName("java.awt.desktop.AboutHandler");\r
+               Object aboutHandler = Proxy.newProxyInstance(Main.class.getClassLoader(),\r
+                               new Class<?>[] { aboutHandlerCls }, new InvocationHandler() {\r
+                                       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+                                               if (method.getName().equals("handleAbout")) {\r
+                                                       MainFrame.getActivedMainFrame().onAbout();\r
+                                                       return null;\r
+                                               }\r
+                                               logger.warning("aboutHandler called=" + method.getName());\r
+                                               return null;\r
+                                       }\r
+                               });\r
+               desktop.getClass().getMethod("setAboutHandler", aboutHandlerCls).invoke(desktop, aboutHandler);\r
+\r
+               Class<?> preferenceHandlerCls = Class.forName("java.awt.desktop.PreferencesHandler");\r
+               Object preferenceHandler = Proxy.newProxyInstance(Main.class.getClassLoader(),\r
+                               new Class<?>[] { preferenceHandlerCls }, new InvocationHandler() {\r
+                                       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+                                               if (method.getName().equals("handlePreferences")) {\r
+                                                       MainFrame.getActivedMainFrame().onPreferences();\r
+                                                       return null;\r
+                                               }\r
+                                               logger.warning("preferenceHandler called=" + method.getName());\r
+                                               return null;\r
+                                       }\r
+                               });\r
+               desktop.getClass().getMethod("setPreferencesHandler",\r
+                               preferenceHandlerCls).invoke(desktop, preferenceHandler);\r
+\r
+               Class<?> quitHandlerCls = Class.forName("java.awt.desktop.QuitHandler");\r
+               Object quitHandler = Proxy.newProxyInstance(Main.class.getClassLoader(),\r
+                               new Class<?>[] { quitHandlerCls }, new InvocationHandler() {\r
+                                       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+                                               if (method.getName().equals("handleQuitRequestWith")) {\r
+                                                       MainFrame.closeAllProfiles();\r
+                                                       System.exit(0);\r
+                                                       return null;\r
+                                               }\r
+                                               logger.warning("quitHandler called=" + method.getName());\r
+                                               return null;\r
+                                       }\r
+                               });\r
+               desktop.getClass().getMethod("setQuitHandler", quitHandlerCls).invoke(desktop, quitHandler);\r
+       }\r
+}\r
index 8bc757a..109942c 100644 (file)
@@ -16,7 +16,7 @@ public class SpinnerWheelSupportListener implements MouseWheelListener {
         * 対象となるスピナーのモデル\r
         */\r
        protected SpinnerModel model;\r
-       \r
+\r
        /**\r
         * スピナーのモデルを指定して構築します.\r
         * @param model\r
@@ -27,13 +27,14 @@ public class SpinnerWheelSupportListener implements MouseWheelListener {
                }\r
                this.model = model;\r
        }\r
-       \r
+\r
        /**\r
         * ホイールによりスピナーモデルの現在値を上下させる.<br>\r
         * モデルが数値型である場合は範囲チェックをし、その範囲で適用します.<br>\r
         * 数値外であれば適用した結果エラーとなる場合は単に無視します.<br>\r
         * @param e マウスホイールイベント\r
         */\r
+       @SuppressWarnings({ "rawtypes", "unchecked" })\r
        public void mouseWheelMoved(MouseWheelEvent e) {\r
                int rotate = e.getWheelRotation();\r
                Object nextval = null;\r
@@ -45,17 +46,15 @@ public class SpinnerWheelSupportListener implements MouseWheelListener {
                        // 下スクロール(down)\r
                        nextval = model.getPreviousValue();\r
                }\r
-               \r
+\r
                if (nextval != null) {\r
                        if (model instanceof SpinnerNumberModel) {\r
                                SpinnerNumberModel nmodel = (SpinnerNumberModel) model;\r
-                               @SuppressWarnings("unchecked")\r
-                               Comparable<Number> max = nmodel.getMaximum();\r
-                               @SuppressWarnings("unchecked")\r
-                               Comparable<Number> min = nmodel.getMinimum();\r
-                               if (max.compareTo((Number) nextval) < 0) {\r
+                               Comparable max = nmodel.getMaximum();\r
+                               Comparable min = nmodel.getMinimum();\r
+                               if (max.compareTo(nextval) < 0) {\r
                                        nextval = null;\r
-                               } else if (min.compareTo((Number) nextval) > 0) {\r
+                               } else if (min.compareTo(nextval) > 0) {\r
                                        nextval = null;\r
                                }\r
                        }\r
@@ -63,12 +62,12 @@ public class SpinnerWheelSupportListener implements MouseWheelListener {
                                if (nextval != null) {\r
                                        model.setValue(nextval);\r
                                }\r
-                               \r
+\r
                        } catch (IllegalArgumentException ex) {\r
                                // 範囲外になった場合はIllegalArgumentExceptionが発生するが、\r
                                // ユーザ操作によるものなので単に無視する\r
                        }\r
                }\r
        }\r
-       \r
+\r
 }\r