OSDN Git Service

refactoring: factory functions in Menu and ContextMenu
[stew/Stew4.git] / src / net / argius / stew / ui / window / Menu.java
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;
+    }
+
 }