OSDN Git Service

e97e3f6acc250179c72ca7937889f2cdaa7cc24c
[stew/Stew4.git] / src / net / argius / stew / ui / window / Menu.java
1 package net.argius.stew.ui.window;
2
3 import static net.argius.stew.ui.window.Menu.Item.*;
4 import static net.argius.stew.ui.window.Utilities.getImageIcon;
5
6 import java.awt.*;
7 import java.beans.*;
8 import java.io.*;
9 import java.util.*;
10 import java.util.Map.Entry;
11 import java.util.List;
12 import java.util.regex.*;
13
14 import javax.swing.*;
15
16 import net.argius.stew.*;
17
18 /**
19  * The menu bar.
20  */
21 final class Menu extends JMenuBar implements PropertyChangeListener {
22
23     private static final ResourceManager res = ResourceManager.getInstance(Menu.class);
24
25     /**
26      * Menu Items.
27      */
28     enum Item {
29         newWindow,
30         closeWindow,
31         quit,
32         cut,
33         copy,
34         paste,
35         selectAll,
36         find,
37         toggleFocus,
38         clearMessage,
39         showStatusBar,
40         showColumnNumber,
41         showInfoTree,
42         showAlwaysOnTop,
43         refresh,
44         widenColumnWidth,
45         narrowColumnWidth,
46         adjustColumnWidth,
47         autoAdjustMode,
48         autoAdjustModeNone,
49         autoAdjustModeHeader,
50         autoAdjustModeValue,
51         autoAdjustModeHeaderAndValue,
52         executeCommand,
53         breakCommand,
54         lastHistory,
55         nextHistory,
56         sendRollback,
57         sendCommit,
58         connect,
59         disconnect,
60         postProcessMode,
61         postProcessModeNone,
62         postProcessModeFocus,
63         postProcessModeShake,
64         postProcessModeBlink,
65         inputEcryptionKey,
66         editConnectors,
67         sortResult,
68         importFile,
69         exportFile,
70         showHelp,
71         showAbout,
72         unknown;
73         static Item of(String name) {
74             try {
75                 return valueOf(name);
76             } catch (IllegalArgumentException ex) {
77                 return unknown;
78             }
79         }
80     }
81
82     private List<JMenuItem> lockingTargets;
83     private List<JMenuItem> unlockingTargets;
84     private EnumMap<Item, JMenuItem> itemToCompMap;
85
86     Menu(final AnyActionListener anyActionListener) {
87         this.lockingTargets = new ArrayList<JMenuItem>();
88         this.unlockingTargets = new ArrayList<JMenuItem>();
89         this.itemToCompMap = new EnumMap<Item, JMenuItem>(Item.class);
90         Map<String, JMenuItem> itemMap = new HashMap<String, JMenuItem>();
91         AnyAction aa = new AnyAction(anyActionListener);
92         for (final String groupId : res.get("groups").split(",", -1)) {
93             JMenu m = add(createJMenu(res, groupId));
94             for (final JMenuItem o : createJMenuItems(res, itemMap, "group." + groupId)) {
95                 if (o == null) {
96                     m.add(new JSeparator());
97                     continue;
98                 }
99                 m.add(o);
100                 final String itemId = o.getActionCommand();
101                 Item itemEnum = Item.of(itemId);
102                 o.addActionListener(aa);
103                 itemToCompMap.put(itemEnum, o);
104                 switch (itemEnum) {
105                     case closeWindow:
106                     case quit:
107                     case cut:
108                     case copy:
109                     case paste:
110                     case selectAll:
111                     case find:
112                     case clearMessage:
113                     case refresh:
114                     case widenColumnWidth:
115                     case narrowColumnWidth:
116                     case adjustColumnWidth:
117                     case autoAdjustMode:
118                     case executeCommand:
119                     case lastHistory:
120                     case nextHistory:
121                     case connect:
122                     case disconnect:
123                     case postProcessMode:
124                     case sortResult:
125                     case exportFile:
126                         lockingTargets.add(o);
127                         break;
128                     case breakCommand:
129                         unlockingTargets.add(o);
130                         break;
131                     default:
132                 }
133             }
134         }
135         for (JMenuItem parent : Arrays.asList(itemToCompMap.get(autoAdjustMode),
136                                               itemToCompMap.get(postProcessMode))) {
137             for (MenuElement menuGroup : parent.getSubElements()) {
138                 for (MenuElement child : menuGroup.getSubElements()) {
139                     JMenuItem o = (JMenuItem)child;
140                     itemToCompMap.put(Item.of(o.getActionCommand()), o);
141                 }
142             }
143         }
144         refreshAllAccelerators(itemMap);
145         setEnabledStates(false);
146     }
147
148     @Override
149     public void propertyChange(PropertyChangeEvent e) {
150         final String propertyName = e.getPropertyName();
151         final Object source = e.getSource();
152         if (source instanceof JLabel && propertyName.equals("ancestor")) {
153             itemToCompMap.get(showStatusBar).setSelected(((JLabel)source).isVisible());
154         } else if (source instanceof ResultSetTable && propertyName.equals("showNumber")) {
155             itemToCompMap.get(showColumnNumber).setSelected((Boolean)e.getNewValue());
156         } else if (source instanceof DatabaseInfoTree) {
157             itemToCompMap.get(showInfoTree).setSelected(((Component)source).isEnabled());
158         } else if (source instanceof JFrame && propertyName.equals("alwaysOnTop")) {
159             itemToCompMap.get(showAlwaysOnTop).setSelected((Boolean)e.getNewValue());
160         } else if (source instanceof ResultSetTable && propertyName.equals("autoAdjustMode")) {
161             final String itemName = e.getNewValue().toString();
162             if (!itemName.matches("[A-Z_]+")) { // ignore old version
163                 itemToCompMap.get(Item.of(itemName)).setSelected(true);
164             }
165         } else if (source instanceof WindowOutputProcessor && propertyName.equals("postProcessMode")) {
166             final String itemName = e.getNewValue().toString();
167             if (!itemName.matches("[A-Z_]+")) { // ignore old version
168                 itemToCompMap.get(Item.of(itemName)).setSelected(true);
169             }
170         }
171     }
172
173     /**
174      * Sets the state that command was started or not.
175      * @param commandStarted
176      */
177     void setEnabledStates(boolean commandStarted) {
178         final boolean lockingTargetsState = !commandStarted;
179         for (JMenuItem item : lockingTargets) {
180             item.setEnabled(lockingTargetsState);
181         }
182         final boolean unlockingTargetsState = commandStarted;
183         for (JMenuItem item : unlockingTargets) {
184             item.setEnabled(unlockingTargetsState);
185         }
186     }
187
188     // Menu factory utilities
189
190     private static JMenu createJMenu(ResourceManager rm, String groupId) {
191         final String key = (rm.containsKey("group." + groupId) ? "group" : "item") + '.' + groupId;
192         final char mn = rm.getChar(key + ".mnemonic");
193         final boolean autoMnemonic = rm.getInt("auto-mnemonic") == 1;
194         final String groupString = rm.get(key) + (autoMnemonic ? "(" + mn + ")" : "");
195         JMenu group = new JMenu(groupString);
196         group.setMnemonic(mn);
197         return group;
198     }
199
200     private static void refreshAllAccelerators(Map<String, JMenuItem> itemMap) {
201         // This method is called everytime menu and popup-menu is created.
202         File keyBindConf = Bootstrap.getSystemFile("keybind.conf");
203         if (!keyBindConf.exists()) {
204             return;
205         }
206         Map<String, KeyStroke> keyMap = new HashMap<String, KeyStroke>();
207         try {
208             Scanner r = new Scanner(keyBindConf);
209             try {
210                 final Pattern p = Pattern.compile("\\s*([^=\\s]+)\\s*=(.*)");
211                 while (r.hasNextLine()) {
212                     final String line = r.nextLine();
213                     if (line == null) {
214                         break;
215                     }
216                     if (line.trim().length() == 0 || line.matches("\\s*#.*")) {
217                         continue;
218                     }
219                     Matcher m = p.matcher(line);
220                     if (m.matches()) {
221                         keyMap.put(m.group(1), Utilities.getKeyStroke(m.group(2)));
222                     }
223                 }
224             } finally {
225                 r.close();
226             }
227         } catch (FileNotFoundException ex) {
228             throw new RuntimeException(ex);
229         }
230         for (final Entry<String, KeyStroke> entry : keyMap.entrySet()) {
231             final String k = entry.getKey();
232             if (itemMap.containsKey(k)) {
233                 itemMap.get(k).setAccelerator(entry.getValue());
234             }
235         }
236     }
237
238     static List<JMenuItem> createJMenuItems(ResourceManager rm, String groupKey) {
239         HashMap<String, JMenuItem> itemMap = new HashMap<String, JMenuItem>();
240         List<JMenuItem> a = createJMenuItems(rm, itemMap, groupKey);
241         refreshAllAccelerators(itemMap);
242         return a;
243     }
244
245     static List<JMenuItem> createJMenuItems(ResourceManager rm,
246                                             Map<String, JMenuItem> itemMap,
247                                             String groupKey) {
248         List<JMenuItem> a = new ArrayList<JMenuItem>();
249         for (final String itemId : rm.get(groupKey + ".items").split(",", -1)) {
250             if (itemId.length() == 0) {
251                 a.add(null);
252             } else {
253                 JMenuItem o = createJMenuItem(rm, itemId);
254                 a.add(o);
255                 itemMap.put(itemId, o);
256             }
257         }
258         return a;
259     }
260
261     static JMenuItem createJMenuItem(ResourceManager rm, String itemId) {
262         final boolean autoMnemonic = rm.getInt("auto-mnemonic") == 1;
263         final String itemKey = "item." + itemId;
264         final char mn = rm.getChar(itemKey + ".mnemonic");
265         final String shortcutKey = itemKey + ".shortcut";
266         final JMenuItem o;
267         if (rm.isTrue(itemKey + ".checkbox")) {
268             o = new JCheckBoxMenuItem();
269         } else if (rm.isTrue(itemKey + ".subgroup")) {
270             o = createJMenu(rm, itemId);
271             ButtonGroup buttonGroup = new ButtonGroup();
272             boolean selected = false;
273             for (final String id : rm.get(itemKey + ".items").split(",", -1)) {
274                 final JMenuItem sub = createJMenuItem(rm, itemId + id);
275                 o.add(sub);
276                 buttonGroup.add(sub);
277                 if (!selected) {
278                     sub.setSelected(true);
279                     selected = true;
280                 }
281             }
282         } else {
283             o = new JMenuItem();
284         }
285         if (rm.containsKey(shortcutKey)) {
286             KeyStroke ks = Utilities.getKeyStroke(rm.get(shortcutKey));
287             if (ks != null) {
288                 o.setAccelerator(ks);
289             }
290         }
291         o.setText(rm.get(itemKey) + (autoMnemonic ? "(" + mn + ")" : ""));
292         o.setMnemonic(mn);
293         o.setActionCommand(itemId);
294         o.setIcon(getImageIcon(String.format("menu-%s.png", itemId)));
295         o.setDisabledIcon(getImageIcon(String.format("menu-disabled-%s.png", itemId)));
296         return o;
297     }
298
299 }