OSDN Git Service

OSXのスクリーンメニュー表示タイミングの修正
[charactermanaj/CharacterManaJ.git] / src / main / java / charactermanaj / Main.java
index 4102f4d..52a0663 100644 (file)
@@ -1,10 +1,12 @@
 package charactermanaj;
 
 import java.awt.Font;
+import java.awt.Frame;
 import java.awt.GraphicsEnvironment;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.lang.Thread.UncaughtExceptionHandler;
-import java.lang.reflect.Method;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Locale;
@@ -24,6 +26,8 @@ import charactermanaj.graphics.io.ImageCacheMBeanImpl;
 import charactermanaj.model.AppConfig;
 import charactermanaj.model.util.StartupSupport;
 import charactermanaj.ui.MainFrame;
+import charactermanaj.ui.MainFramePartialForMacOSX;
+import charactermanaj.ui.MainFramePartialForMacOSX9;
 import charactermanaj.ui.ProfileListManager;
 import charactermanaj.ui.SelectCharatersDirDialog;
 import charactermanaj.util.AWTExceptionLoggingHandler;
@@ -36,7 +40,7 @@ import charactermanaj.util.LocalizedResourcePropertyLoader;
 
 /**
  * エントリポイント用クラス
- * 
+ *
  * @author seraphy
  */
 public final class Main implements Runnable {
@@ -119,11 +123,11 @@ public final class Main implements Runnable {
 
        /**
         * UIをセットアップする.
-        * 
+        *
         * @throws Exception
         *             いろいろな失敗
         */
-       private static void setupUIManager(AppConfig appConfig) throws Exception {
+       private static void setupUIManager(final AppConfig appConfig) throws Exception {
                // System.setProperty("swing.aatext", "true");
                // System.setProperty("awt.useSystemAAFontSettings", "on");
 
@@ -146,21 +150,45 @@ public final class Main implements Runnable {
                // JSpliderのvalueを非表示 (GTKではデフォルトで有効のため)
                UIManager.put("Slider.paintValue", Boolean.FALSE);
 
+               // デフォルトフォントを設定する
+               setupDefaultFont(appConfig);
+
+               // アプリケーション設定でデフォルトフォントサイズが変更された場合は
+               // 現在表示されている、すべてのフレームに再適用を試行する。
+               appConfig.addPropertyChangeListener(AppConfig.DEFAULT_FONT_SIZE, new PropertyChangeListener() {
+                       @Override
+                       public void propertyChange(PropertyChangeEvent evt) {
+                               setupDefaultFont(appConfig);
+                               try {
+                                       for (Frame frame : Frame.getFrames()) {
+                                               SwingUtilities.updateComponentTreeUI(frame);
+                                       }
+                               } catch (Exception ex) {
+                                       logger.log(Level.WARNING, "failed revalidate frames", ex);
+                               }
+                       }
+               });
+       }
+
+       private static void setupDefaultFont(AppConfig appConfig) {
 
                // 優先するフォントファミリ中の実在するフォントファミリのセット(大文字小文字の区別なし)
                TreeSet<String> availablePriorityFontSets = new TreeSet<String>(
                                String.CASE_INSENSITIVE_ORDER);
-               
+
                // 少なくともメニューが表示できるようなフォントを選択する
                Properties strings = LocalizedResourcePropertyLoader.getCachedInstance()
                                .getLocalizedProperties("menu/menu");
-               HashSet<Character> useChars = new HashSet<Character>();
+               HashSet<Integer> useCodePoints = new HashSet<Integer>();
                Enumeration<?> enmStrings = strings.propertyNames();
                while (enmStrings.hasMoreElements()) {
                        String propertyName = (String) enmStrings.nextElement();
                        String propertyValue = strings.getProperty(propertyName);
-                       for (char ch : propertyValue.toCharArray()) {
-                               useChars.add(ch);
+                       int len = propertyValue.length();
+                       for (int idx = 0; idx < len;) {
+                               int codepoint = propertyValue.codePointAt(idx);
+                               useCodePoints.add(codepoint);
+                               idx += Character.charCount(codepoint);
                        }
                }
 
@@ -179,12 +207,11 @@ public final class Main implements Runnable {
                                                        Font font = Font.decode(availableFontFamily);
                                                        logger.log(Level.INFO, "実在するフォントの確認:" + availableFontFamily);
                                                        boolean canDisplay = false;
-                                                       for (char ch : useChars) {
-                                                               canDisplay = font.canDisplay(ch);
+                                                       for (Integer codepoint : useCodePoints) {
+                                                               canDisplay = font.canDisplay(codepoint);
                                                                if (!canDisplay) {
-                                                                       logger.log(Level.INFO,
-                                                                                       "このフォントはメニュー表示に使用できません: "
-                                                                                                       + selectedFontFamily + "/ch=" + ch);
+                                                                       logger.log(Level.INFO, "このフォントはメニュー表示に使用できません: "
+                                                                                       + selectedFontFamily + "/codepoint=0x" + Integer.toHexString(codepoint));
                                                                        break;
                                                                }
                                                        }
@@ -206,7 +233,7 @@ public final class Main implements Runnable {
                                selectedFontFamily = "Dialog";
                        }
                }
-               
+
                // デフォルトのフォントサイズ、0以下の場合はシステム標準のまま
                int defFontSize = appConfig.getDefaultFontSize();
 
@@ -221,7 +248,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 +263,7 @@ public final class Main implements Runnable {
                                        }
                                        fontFamily = selectedFontFamily;
                                }
-                               
+
                                fontUIResource = new FontUIResource(fontFamily,
                                                fontUIResource.getStyle(), fontSize);
                                UIManager.put(entry.getKey(), fontUIResource);
@@ -290,6 +317,11 @@ public final class Main implements Runnable {
                                }
                        }
 
+                       // スタートアップ時の初期化
+                       // ver0.999ではキャラクターデータディレクトリに依存しない初期化部しかないので最初に実行する。
+                       // (APPDATAからLOCALAPPDATAへの移動処理などがあるため、先に行う必要がある。)
+                       StartupSupport.getInstance().doStartup();
+
                        // 起動時のシステムプロパティでキャラクターディレクトリが指定されていて実在すれば、それを優先する.
                        File currentCharacterDir = null;
                        String charactersDir = System.getProperty("charactersDir");
@@ -300,15 +332,38 @@ public final class Main implements Runnable {
                                }
                        }
 
+                       // OSXであれば、DockIconを先に設定する
+                       if (isMacOSX()) {
+                               try {
+                                       if (JavaVersionUtils.getJavaVersion() >= 9) {
+                                               // OSXでJava9以降であればOracle実装でDockIconを設定する.
+                                               MainFramePartialForMacOSX9.setupDockIcon();
+
+                                               // スクリーンメニュー類を設定する.
+                                               // (メニュー項目は、その時点でアクティブになっているメインフレームに転送される)
+                                               MainFramePartialForMacOSX9.setupScreenMenu();
+
+                                       } else {
+                                               // Java9未満であればeawtでDockIcon類を設定する.
+                                               MainFramePartialForMacOSX.setupDockIcon();
+
+                                               // スクリーンメニューからのイベントをハンドルできるようにする.
+                                               // (メニュー項目は、その時点でアクティブになっているメインフレームに転送される)
+                                               MainFramePartialForMacOSX.setupScreenMenu();
+                                       }
+
+                               } catch (Throwable ex) {
+                                       logger.log(Level.CONFIG, "Failed to setup the dock icon.", ex);
+                               }
+                       }
+
                        if (currentCharacterDir == null) {
                                // キャラクターセットディレクトリの選択
-                               File defaultCharacterDir = ConfigurationDirUtilities
-                                               .getDefaultCharactersDir();
-                               currentCharacterDir = SelectCharatersDirDialog
-                                               .getCharacterDir(defaultCharacterDir);
+                               File defaultCharacterDir = ConfigurationDirUtilities.getDefaultCharactersDir();
+                               currentCharacterDir = SelectCharatersDirDialog.getCharacterDir(defaultCharacterDir);
                                if (currentCharacterDir == null) {
                                        // キャンセルされたので終了する.
-                                       logger.info("luncher canceled.");
+                                       logger.info("launcher canceled.");
                                        return;
                                }
                        }
@@ -316,29 +371,9 @@ public final class Main implements Runnable {
                        // キャラクターデータフォルダの設定
                        DirectoryConfig.getInstance().setCharactersDir(currentCharacterDir);
 
-                       // スタートアップ時の初期化
-                       StartupSupport.getInstance().doStartup();
-
                        // デフォルトのプロファイルを開く.
                        // (最後に使ったプロファイルがあれば、それが開かれる.)
-                       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);
-
-                               } catch (Throwable ex) {
-                                       logger.log(Level.CONFIG,
-                                                       "The Apple Java Extensions is not found.", ex);
-                               }
-                       }
+                       final MainFrame mainFrame = ProfileListManager.openDefaultProfile();
 
                        // 表示(および位置あわせ)
                        mainFrame.showMainFrame();
@@ -358,7 +393,7 @@ public final class Main implements Runnable {
        /**
         * エントリポイント.<br>
         * 最初のメインフレームを開いたときにMac OS Xであればスクリーンメニューの登録も行う.<br>
-        * 
+        *
         * @param args
         *            引数(未使用)
         */
@@ -381,7 +416,7 @@ public final class Main implements Runnable {
 
        /**
         * Mac OS Xで動作しているか?
-        * 
+        *
         * @return Max OS X上であればtrue
         */
        public static boolean isMacOSX() {
@@ -390,7 +425,7 @@ public final class Main implements Runnable {
 
        /**
         * Mac OS X、もしくはlinuxで動作しているか?
-        * 
+        *
         * @return Mac OS X、もしくはlinuxで動作していればtrue
         */
        public static boolean isLinuxOrMacOSX() {