OSDN Git Service

refactoring: factory functions in Menu and ContextMenu
authorargius <argius.net@gmail.com>
Wed, 8 May 2013 12:32:16 +0000 (21:32 +0900)
committerargius <argius.net@gmail.com>
Wed, 8 May 2013 12:32:16 +0000 (21:32 +0900)
src/net/argius/stew/ui/window/ContextMenu.java
src/net/argius/stew/ui/window/Menu.java
src/net/argius/stew/ui/window/WindowLauncher.java

index 99426e4..0e07dc6 100644 (file)
@@ -15,45 +15,31 @@ final class ContextMenu {
     private static final Logger log = Logger.getLogger(ContextMenu.class);
     private static final ResourceManager res = ResourceManager.getInstance(ContextMenu.class);
 
-    static JPopupMenu create(final JComponent target, final AnyActionListener dst) {
+    static JPopupMenu create(JComponent target, AnyActionListener dst) {
         return create(target, dst, target.getClass().getSimpleName());
     }
 
-    static JPopupMenu create(final AnyActionListener dst) {
+    static JPopupMenu create(AnyActionListener dst) {
         JComponent c = (dst instanceof JComponent) ? (JComponent)dst : null;
         return create(c, dst, dst.getClass().getSimpleName());
     }
 
-    static JPopupMenu create(final JComponent target, final AnyActionListener dst, String name) {
+    static JPopupMenu create(JComponent target, AnyActionListener dst, String name) {
         log.atEnter("set", dst, name);
-        final JPopupMenu menu = new JPopupMenu();
-        final Map<String, KeyStroke> keyBounds = extractKeyBinds(target);
-        final boolean autoMnemonic = res.getInt("auto-mnemonic") == 1;
+        JPopupMenu menu = new JPopupMenu();
+        Map<String, KeyStroke> keyBounds = extractKeyBinds(target);
         AnyAction aa = new AnyAction(dst);
-        for (final String itemId : res.get(name + ".items").split(",", -1)) {
-            if (itemId.length() == 0) {
+        for (JMenuItem o : Menu.createJMenuItems(res, name)) {
+            if (o == null) {
                 menu.add(new JSeparator());
                 continue;
             }
-            final String id = "item." + itemId;
-            final JMenuItem item = new JMenuItem(itemId);
-            final char mn = res.getChar(id + ".mnemonic");
-            item.setText((res.containsKey(id))
-                    ? res.get(id) + (autoMnemonic ? "(" + mn + ")" : "")
-                    : itemId);
-            item.setMnemonic(mn);
-            item.setActionCommand(itemId);
-            item.addActionListener(aa);
-            final String shortcutId = id + ".shortcut";
-            if (res.containsKey(shortcutId)) {
-                KeyStroke shortcutKey = Utilities.getKeyStroke(res.get(shortcutId));
-                if (shortcutKey != null) {
-                    item.setAccelerator(shortcutKey);
-                }
-            } else if (keyBounds.containsKey(itemId)) {
-                item.setAccelerator(keyBounds.get(itemId));
+            o.addActionListener(aa);
+            final String itemId = o.getActionCommand();
+            if (keyBounds.containsKey(itemId)) {
+                o.setAccelerator(keyBounds.get(itemId));
             }
-            menu.add(item);
+            menu.add(o);
         }
         if (target == null && dst instanceof JComponent) {
             ((JComponent)dst).setComponentPopupMenu(menu);
@@ -82,39 +68,22 @@ final class ContextMenu {
         return m;
     }
 
-    static JPopupMenu createForText(final JTextComponent text) {
+    static JPopupMenu createForText(JTextComponent text) {
         AnyAction aa = new AnyAction(text);
         return createForText(text, aa.setUndoAction());
     }
 
-    static JPopupMenu createForText(final JTextComponent text, UndoManager um) {
-        final JPopupMenu menu = new JPopupMenu();
+    static JPopupMenu createForText(JTextComponent text, UndoManager um) {
+        JPopupMenu menu = new JPopupMenu();
         TextPopupMenuListener textPopupListener = new TextPopupMenuListener(text, um);
-        final boolean autoMnemonic = res.getInt("auto-mnemonic") == 1;
-        final String name = "TextComponent";
-        for (final String itemId : res.get(name + ".items").split(",", -1)) {
-            if (itemId.length() == 0) {
+        for (JMenuItem o : Menu.createJMenuItems(res, "TextComponent")) {
+            if (o == null) {
                 menu.add(new JSeparator());
                 continue;
             }
-            final String id = "item." + itemId;
-            final JMenuItem item = new JMenuItem(itemId);
-            final char mn = res.getChar(id + ".mnemonic");
-            item.setText((res.containsKey(id))
-                    ? res.get(id) + (autoMnemonic ? "(" + mn + ")" : "")
-                    : itemId);
-            item.setMnemonic(mn);
-            item.setActionCommand(itemId);
-            item.addActionListener(textPopupListener);
-            final String shortcutId = id + ".shortcut";
-            if (res.containsKey(shortcutId)) {
-                KeyStroke shortcutKey = Utilities.getKeyStroke(res.get(shortcutId));
-                if (shortcutKey != null) {
-                    item.setAccelerator(shortcutKey);
-                }
-            }
-            menu.add(item);
-            textPopupListener.putPopupMenuItem(itemId, item);
+            menu.add(o);
+            o.addActionListener(textPopupListener);
+            textPopupListener.putPopupMenuItem(o.getActionCommand(), o);
         }
         menu.addPopupMenuListener(textPopupListener);
         text.setComponentPopupMenu(menu);
index 5f42025..e0b96c2 100644 (file)
@@ -2,13 +2,14 @@ package net.argius.stew.ui.window;
 
 import static net.argius.stew.ui.window.Menu.Item.*;
 import static net.argius.stew.ui.window.Utilities.getImageIcon;
-import static net.argius.stew.ui.window.Utilities.getMenuShortcutKeyMask;
 
 import java.awt.*;
-import java.awt.event.*;
 import java.beans.*;
+import java.io.*;
 import java.util.*;
+import java.util.Map.Entry;
 import java.util.List;
+import java.util.regex.*;
 
 import javax.swing.*;
 
@@ -67,48 +68,40 @@ final class Menu extends JMenuBar implements PropertyChangeListener {
         importFile,
         exportFile,
         showHelp,
-        showAbout;
+        showAbout,
+        unknown;
+        static Item of(String name) {
+            try {
+                return valueOf(name);
+            } catch (IllegalArgumentException ex) {
+                return unknown;
+            }
+        }
     }
 
     private List<JMenuItem> lockingTargets;
     private List<JMenuItem> unlockingTargets;
     private EnumMap<Item, JMenuItem> itemToCompMap;
-    private Map<JMenuItem, Item> compToItemMap;
 
     Menu(final AnyActionListener anyActionListener) {
         this.lockingTargets = new ArrayList<JMenuItem>();
         this.unlockingTargets = new ArrayList<JMenuItem>();
         this.itemToCompMap = new EnumMap<Item, JMenuItem>(Item.class);
-        this.compToItemMap = new HashMap<JMenuItem, Item>();
-        final boolean autoMnemonic = res.getInt("auto-mnemonic") == 1;
+        Map<String, JMenuItem> itemMap = new HashMap<String, JMenuItem>();
         AnyAction aa = new AnyAction(anyActionListener);
         for (final String groupId : res.get("groups").split(",", -1)) {
-            final String groupKey = "group." + groupId;
-            JMenu group = add(buildGroup(groupId, autoMnemonic));
-            for (final String itemId : res.get(groupKey + ".items").split(",", -1)) {
-                if (itemId.length() == 0) {
-                    group.add(new JSeparator());
+            JMenu m = add(createJMenu(res, groupId));
+            for (final JMenuItem o : createJMenuItems(res, itemMap, "group." + groupId)) {
+                if (o == null) {
+                    m.add(new JSeparator());
                     continue;
                 }
-                JMenuItem m = group.add(buildItem(itemId, autoMnemonic));
-                Item item;
-                try {
-                    item = Item.valueOf(itemId);
-                } catch (Exception ex) {
-                    assert false : ex.toString();
-                    continue;
-                }
-                m.addActionListener(aa);
-                itemToCompMap.put(item, m);
-                compToItemMap.put(m, item);
-                final String shortcutId = "item." + itemId + ".shortcut";
-                if (res.containsKey(shortcutId)) {
-                    KeyStroke shortcutKey = KeyStroke.getKeyStroke(res.get(shortcutId));
-                    if (shortcutKey != null) {
-                        setAccelerator(item, shortcutKey);
-                    }
-                }
-                switch (item) {
+                m.add(o);
+                final String itemId = o.getActionCommand();
+                Item itemEnum = Item.of(itemId);
+                o.addActionListener(aa);
+                itemToCompMap.put(itemEnum, o);
+                switch (itemEnum) {
                     case closeWindow:
                     case quit:
                     case cut:
@@ -130,69 +123,26 @@ final class Menu extends JMenuBar implements PropertyChangeListener {
                     case postProcessMode:
                     case sortResult:
                     case exportFile:
-                        lockingTargets.add(m);
+                        lockingTargets.add(o);
                         break;
                     case breakCommand:
-                        unlockingTargets.add(m);
+                        unlockingTargets.add(o);
                         break;
                     default:
                 }
             }
         }
-        for (final Item item : EnumSet.of(autoAdjustModeNone,
-                                          autoAdjustModeHeader,
-                                          autoAdjustModeValue,
-                                          autoAdjustModeHeaderAndValue,
-                                          postProcessMode,
-                                          postProcessModeNone,
-                                          postProcessModeFocus,
-                                          postProcessModeShake,
-                                          postProcessModeBlink)) {
-            itemToCompMap.get(item).addActionListener(aa);
-        }
-        setEnabledStates(false);
-    }
-
-    private static JMenu buildGroup(String groupId, boolean autoMnemonic) {
-        final String key = (res.containsKey("group." + groupId) ? "group" : "item") + '.' + groupId;
-        final char mn = res.getChar(key + ".mnemonic");
-        final String groupString = res.get(key) + (autoMnemonic ? "(" + mn + ")" : "");
-        JMenu group = new JMenu(groupString);
-        group.setMnemonic(mn);
-        return group;
-    }
-
-    private JMenuItem buildItem(String itemId, boolean autoMnemonic) {
-        final String itemKey = "item." + itemId;
-        final char mn = res.getChar(itemKey + ".mnemonic");
-        final JMenuItem m;
-        if (res.isTrue(itemKey + ".checkbox")) {
-            m = new JCheckBoxMenuItem();
-        } else if (res.isTrue(itemKey + ".subgroup")) {
-            m = buildGroup(itemId, autoMnemonic);
-            ButtonGroup buttonGroup = new ButtonGroup();
-            boolean selected = false;
-            for (final String id : res.get(itemKey + ".items").split(",", -1)) {
-                final JMenuItem sub = buildItem(itemId + id, autoMnemonic);
-                m.add(sub);
-                buttonGroup.add(sub);
-                if (!selected) {
-                    sub.setSelected(true);
-                    selected = true;
+        for (JMenuItem parent : Arrays.asList(itemToCompMap.get(autoAdjustMode),
+                                              itemToCompMap.get(postProcessMode))) {
+            for (MenuElement menuGroup : parent.getSubElements()) {
+                for (MenuElement child : menuGroup.getSubElements()) {
+                    JMenuItem o = (JMenuItem)child;
+                    itemToCompMap.put(Item.of(o.getActionCommand()), o);
                 }
-                Item subItem = Item.valueOf(itemId + id);
-                itemToCompMap.put(subItem, sub);
-                compToItemMap.put(sub, subItem);
             }
-        } else {
-            m = new JMenuItem();
         }
-        m.setText(res.get(itemKey) + (autoMnemonic ? "(" + mn + ")" : ""));
-        m.setMnemonic(mn);
-        m.setActionCommand(itemId);
-        m.setIcon(getImageIcon(String.format("menu-%s.png", itemId)));
-        m.setDisabledIcon(getImageIcon(String.format("menu-disabled-%s.png", itemId)));
-        return m;
+        refreshAllAccelerators(itemMap);
+        setEnabledStates(false);
     }
 
     @Override
@@ -210,37 +160,17 @@ final class Menu extends JMenuBar implements PropertyChangeListener {
         } else if (source instanceof ResultSetTable && propertyName.equals("autoAdjustMode")) {
             final String itemName = e.getNewValue().toString();
             if (!itemName.matches("[A-Z_]+")) { // ignore old version
-                itemToCompMap.get(Item.valueOf(itemName)).setSelected(true);
+                itemToCompMap.get(Item.of(itemName)).setSelected(true);
             }
         } else if (source instanceof WindowOutputProcessor && propertyName.equals("postProcessMode")) {
             final String itemName = e.getNewValue().toString();
             if (!itemName.matches("[A-Z_]+")) { // ignore old version
-                itemToCompMap.get(Item.valueOf(itemName)).setSelected(true);
+                itemToCompMap.get(Item.of(itemName)).setSelected(true);
             }
         }
     }
 
     /**
-     * Sets a Accelerator (shortcut key).
-     * @param item
-     * @param ks
-     */
-    void setAccelerator(Item item, KeyStroke ks) {
-        int m = 0;
-        final String s = ks.toString();
-        if (s.contains("ctrl")) {
-            m |= getMenuShortcutKeyMask();
-        }
-        if (s.contains("alt")) {
-            m |= InputEvent.ALT_DOWN_MASK;
-        }
-        if (s.contains("shift")) {
-            m |= InputEvent.SHIFT_DOWN_MASK;
-        }
-        itemToCompMap.get(item).setAccelerator(KeyStroke.getKeyStroke(ks.getKeyCode(), m));
-    }
-
-    /**
      * Sets the state that command was started or not.
      * @param commandStarted
      */
@@ -255,4 +185,115 @@ final class Menu extends JMenuBar implements PropertyChangeListener {
         }
     }
 
+    // Menu factory utilities
+
+    private static JMenu createJMenu(ResourceManager rm, String groupId) {
+        final String key = (rm.containsKey("group." + groupId) ? "group" : "item") + '.' + groupId;
+        final char mn = rm.getChar(key + ".mnemonic");
+        final boolean autoMnemonic = rm.getInt("auto-mnemonic") == 1;
+        final String groupString = rm.get(key) + (autoMnemonic ? "(" + mn + ")" : "");
+        JMenu group = new JMenu(groupString);
+        group.setMnemonic(mn);
+        return group;
+    }
+
+    private static void refreshAllAccelerators(Map<String, JMenuItem> itemMap) {
+        // This method is called everytime menu and popup-menu is created.
+        File keyBindConf = new File(Bootstrap.getDirectory(), "keybind.conf");
+        if (!keyBindConf.exists()) {
+            return;
+        }
+        Map<String, KeyStroke> keyMap = new HashMap<String, KeyStroke>();
+        try {
+            Scanner r = new Scanner(keyBindConf);
+            try {
+                final Pattern p = Pattern.compile("\\s*([^=\\s]+)\\s*=(.*)");
+                while (r.hasNextLine()) {
+                    final String line = r.nextLine();
+                    if (line == null) {
+                        break;
+                    }
+                    if (line.trim().length() == 0 || line.matches("\\s*#.*")) {
+                        continue;
+                    }
+                    Matcher m = p.matcher(line);
+                    if (m.matches()) {
+                        keyMap.put(m.group(1), Utilities.getKeyStroke(m.group(2)));
+                    }
+                }
+            } finally {
+                r.close();
+            }
+        } catch (FileNotFoundException ex) {
+            throw new RuntimeException(ex);
+        }
+        for (final Entry<String, KeyStroke> entry : keyMap.entrySet()) {
+            final String k = entry.getKey();
+            if (itemMap.containsKey(k)) {
+                itemMap.get(k).setAccelerator(entry.getValue());
+            }
+        }
+    }
+
+    static List<JMenuItem> createJMenuItems(ResourceManager rm, String groupKey) {
+        HashMap<String, JMenuItem> itemMap = new HashMap<String, JMenuItem>();
+        List<JMenuItem> a = createJMenuItems(rm, itemMap, groupKey);
+        refreshAllAccelerators(itemMap);
+        return a;
+    }
+
+    static List<JMenuItem> createJMenuItems(ResourceManager rm,
+                                            Map<String, JMenuItem> itemMap,
+                                            String groupKey) {
+        List<JMenuItem> a = new ArrayList<JMenuItem>();
+        for (final String itemId : rm.get(groupKey + ".items").split(",", -1)) {
+            if (itemId.length() == 0) {
+                a.add(null);
+            } else {
+                JMenuItem o = createJMenuItem(rm, itemId);
+                a.add(o);
+                itemMap.put(itemId, o);
+            }
+        }
+        return a;
+    }
+
+    static JMenuItem createJMenuItem(ResourceManager rm, String itemId) {
+        final boolean autoMnemonic = rm.getInt("auto-mnemonic") == 1;
+        final String itemKey = "item." + itemId;
+        final char mn = rm.getChar(itemKey + ".mnemonic");
+        final String shortcutKey = itemKey + ".shortcut";
+        final JMenuItem o;
+        if (rm.isTrue(itemKey + ".checkbox")) {
+            o = new JCheckBoxMenuItem();
+        } else if (rm.isTrue(itemKey + ".subgroup")) {
+            o = createJMenu(rm, itemId);
+            ButtonGroup buttonGroup = new ButtonGroup();
+            boolean selected = false;
+            for (final String id : rm.get(itemKey + ".items").split(",", -1)) {
+                final JMenuItem sub = createJMenuItem(rm, itemId + id);
+                o.add(sub);
+                buttonGroup.add(sub);
+                if (!selected) {
+                    sub.setSelected(true);
+                    selected = true;
+                }
+            }
+        } else {
+            o = new JMenuItem();
+        }
+        if (rm.containsKey(shortcutKey)) {
+            KeyStroke ks = Utilities.getKeyStroke(rm.get(shortcutKey));
+            if (ks != null) {
+                o.setAccelerator(ks);
+            }
+        }
+        o.setText(rm.get(itemKey) + (autoMnemonic ? "(" + mn + ")" : ""));
+        o.setMnemonic(mn);
+        o.setActionCommand(itemId);
+        o.setIcon(getImageIcon(String.format("menu-%s.png", itemId)));
+        o.setDisabledIcon(getImageIcon(String.format("menu-disabled-%s.png", itemId)));
+        return o;
+    }
+
 }
index 523d0b8..3c69638 100644 (file)
@@ -3,7 +3,6 @@ package net.argius.stew.ui.window;
 import static java.awt.event.ActionEvent.ACTION_PERFORMED;
 import static javax.swing.JOptionPane.*;
 import static javax.swing.JSplitPane.VERTICAL_SPLIT;
-import static javax.swing.KeyStroke.getKeyStroke;
 import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER;
 import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS;
 import static net.argius.stew.ui.window.AnyActionKey.*;
@@ -19,7 +18,6 @@ import java.util.Map.Entry;
 import java.util.List;
 import java.util.Timer;
 import java.util.concurrent.*;
-import java.util.regex.*;
 
 import javax.swing.*;
 import javax.swing.event.*;
@@ -28,7 +26,6 @@ import javax.swing.text.*;
 
 import net.argius.stew.*;
 import net.argius.stew.ui.*;
-import net.argius.stew.ui.window.Menu.Item;
 
 /**
  * The Launcher implementation for GUI(Swing).
@@ -607,37 +604,6 @@ public final class WindowLauncher implements
         op.showErrorDialog(th);
     }
 
-    /**
-     * Changes key binds.
-     * @param keyBindInfos key bind infos (info is String value of KeyStroke)
-     */
-    static void changeKeyBinds(List<String> keyBindInfos) {
-        final Pattern p = Pattern.compile("\\s*([^=\\s]+)\\s*=(.*)");
-        List<String> errorInfos = new ArrayList<String>();
-        for (String s : keyBindInfos) {
-            if (s.trim().length() == 0 || s.matches("\\s*#.*")) {
-                continue;
-            }
-            Matcher m = p.matcher(s);
-            if (m.matches()) {
-                try {
-                    Item item = Item.valueOf(m.group(1));
-                    KeyStroke keyStroke = getKeyStroke(m.group(2));
-                    for (WindowLauncher instance : instances) {
-                        instance.menu.setAccelerator(item, keyStroke);
-                    }
-                } catch (Exception ex) {
-                    errorInfos.add(s);
-                }
-            } else {
-                errorInfos.add(s);
-            }
-        }
-        if (!errorInfos.isEmpty()) {
-            throw new IllegalArgumentException(errorInfos.toString());
-        }
-    }
-
     static void invoke() {
         invoke(new WindowLauncher());
     }
@@ -646,24 +612,6 @@ public final class WindowLauncher implements
         final Environment env = new Environment();
         env.setOutputProcessor(new WindowOutputProcessor.Bypass(instance.op));
         instance.launch(env);
-        // applies key binds
-        try {
-            File keyBindConf = new File(Bootstrap.getDirectory(), "keybind.conf");
-            if (keyBindConf.exists()) {
-                List<String> a = new ArrayList<String>();
-                Scanner scanner = new Scanner(keyBindConf);
-                try {
-                    while (scanner.hasNextLine()) {
-                        a.add(scanner.nextLine());
-                    }
-                } finally {
-                    scanner.close();
-                }
-                changeKeyBinds(a);
-            }
-        } catch (Exception ex) {
-            instance.handleError(ex);
-        }
     }
 
     /**