001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.options.keymap;
043:
044: import java.awt.event.ActionEvent;
045: import java.io.File;
046: import java.io.FileWriter;
047: import java.io.IOException;
048: import java.io.OutputStream;
049: import java.io.OutputStreamWriter;
050: import java.io.Writer;
051: import java.util.ArrayList;
052: import java.util.Collections;
053: import java.util.HashMap;
054: import java.util.Iterator;
055: import java.util.List;
056: import java.util.Map;
057: import java.util.Set;
058: import java.util.TreeMap;
059: import javax.swing.AbstractAction;
060: import javax.swing.Action;
061: import javax.swing.JFileChooser;
062: import org.netbeans.core.options.keymap.api.ShortcutAction;
063: import org.netbeans.core.options.keymap.spi.KeymapManager;
064: import org.netbeans.modules.options.keymap.XMLStorage.Attribs;
065: import org.openide.ErrorManager;
066: import org.openide.filesystems.FileLock;
067: import org.openide.filesystems.FileObject;
068: import org.openide.filesystems.FileUtil;
069: import org.openide.filesystems.Repository;
070: import org.openide.loaders.DataObject;
071: import org.openide.util.NbBundle;
072: import org.openide.windows.WindowManager;
073:
074: public class ExportShortcutsAction {
075:
076: private ExportShortcutsAction() {
077: }
078:
079: private static Action exportIDEActionsAction = new AbstractAction() {
080: {
081: putValue(Action.NAME, loc("CTL_Export_IDE_Actions_Action"));
082: }
083:
084: public void actionPerformed(ActionEvent e) {
085:
086: // 1) load all keymaps to allKeyMaps
087: LayersBridge layersBridge = new LayersBridge();
088: Map<String, Set<ShortcutAction>> categoryToActions = layersBridge
089: .getActions();
090: Map<String, Map<String, ShortcutAction>> m = resolveNames(categoryToActions);
091:
092: generateLayersXML(layersBridge, m);
093: }
094: };
095:
096: public static Action getExportIDEActionsAction() {
097: return exportIDEActionsAction;
098: }
099:
100: private static Action exportIDEShortcutsAction = new AbstractAction() {
101: {
102: putValue(Action.NAME,
103: loc("CTL_Export_IDE_Shortcuts_Action"));
104: }
105:
106: public void actionPerformed(ActionEvent e) {
107:
108: // 1) load all keymaps to allKeyMaps
109: Map<String, Map<String, ShortcutAction>> allKeyMaps = new HashMap<String, Map<String, ShortcutAction>>();
110: LayersBridge layersBridge = new LayersBridge();
111: layersBridge.getActions();
112: List keyMaps = layersBridge.getProfiles();
113: Iterator it3 = keyMaps.iterator();
114: while (it3.hasNext()) {
115: String keyMapName = (String) it3.next();
116: Map<ShortcutAction, Set<String>> actionToShortcuts = layersBridge
117: .getKeymap(keyMapName);
118: Map<String, ShortcutAction> shortcutToAction = LayersBridge
119: .shortcutToAction(actionToShortcuts);
120: allKeyMaps.put(keyMapName, shortcutToAction);
121: }
122:
123: generateLayersXML(layersBridge, allKeyMaps);
124: }
125: };
126:
127: public static Action getExportIDEShortcutsAction() {
128: return exportIDEShortcutsAction;
129: }
130:
131: private static Action exportEditorShortcutsAction = new AbstractAction() {
132: {
133: putValue(Action.NAME,
134: loc("CTL_Export_Editor_Shortcuts_Action"));
135: }
136:
137: public void actionPerformed(ActionEvent e) {
138: KeymapManager editorBridge = null;
139: for (KeymapManager km : KeymapModel
140: .getKeymapManagerInstances()) {
141: if ("EditorBridge".equals(km.getName())) {
142: editorBridge = km;
143: break;
144: }
145: }
146: if (editorBridge != null) {
147: Map<ShortcutAction, Set<String>> actionToShortcuts = editorBridge
148: .getKeymap(editorBridge.getCurrentProfile());
149: generateEditorXML(actionToShortcuts);
150: }
151: }
152: };
153:
154: public static Action getExportEditorShortcutsAction() {
155: return exportEditorShortcutsAction;
156: }
157:
158: private static Action exportShortcutsToHTMLAction = new AbstractAction() {
159: {
160: putValue(Action.NAME,
161: loc("CTL_Export_Shortcuts_to_HTML_Action"));
162: }
163:
164: public void actionPerformed(ActionEvent e) {
165: exportShortcutsToHTML();
166: }
167: };
168:
169: public static Action getExportShortcutsToHTMLAction() {
170: return exportShortcutsToHTMLAction;
171: }
172:
173: // helper methods ..........................................................
174:
175: private static void exportShortcutsToHTML() {
176: // read all shortcuts to keymaps
177: KeymapModel keymapModel = new KeymapModel();
178: Map<String, Map<ShortcutAction, Set<String>>> keymaps = new TreeMap<String, Map<ShortcutAction, Set<String>>>();
179: for (String profile : keymapModel.getProfiles()) {
180: keymaps.put(profile, keymapModel.getKeymap(profile));
181: }
182:
183: try {
184: StringBuffer sb = new StringBuffer();
185:
186: Attribs attribs = new Attribs(true);
187: XMLStorage.generateFolderStart(sb, "html", attribs, "");
188: XMLStorage.generateFolderStart(sb, "body", attribs, " ");
189: attribs.add("border", "1");
190: attribs.add("cellpadding", "1");
191: attribs.add("cellspacing", "0");
192: XMLStorage
193: .generateFolderStart(sb, "table", attribs, " ");
194: attribs = new Attribs(true);
195:
196: // print header of table
197: XMLStorage.generateFolderStart(sb, "tr", attribs, " ");
198: XMLStorage.generateFolderStart(sb, "td", attribs,
199: " ");
200: XMLStorage.generateFolderStart(sb, "h2", attribs,
201: " ");
202: sb.append("Action Name");
203: XMLStorage.generateFolderEnd(sb, "h2", " ");
204: XMLStorage.generateFolderEnd(sb, "td", " ");
205: for (String profile : keymaps.keySet()) {
206: XMLStorage.generateFolderStart(sb, "td", attribs,
207: " ");
208: XMLStorage.generateFolderStart(sb, "h2", attribs,
209: " ");
210: sb.append(profile);
211: XMLStorage.generateFolderEnd(sb, "h2", " ");
212: XMLStorage.generateFolderEnd(sb, "td", " ");
213: }
214:
215: // print body of table
216: exportShortcutsToHTML2(keymapModel, sb, keymaps);
217:
218: XMLStorage.generateFolderEnd(sb, "table", " ");
219: XMLStorage.generateFolderEnd(sb, "body", " ");
220: XMLStorage.generateFolderEnd(sb, "html", "");
221:
222: FileObject fo = FileUtil
223: .createData(Repository.getDefault()
224: .getDefaultFileSystem().getRoot(),
225: "shortcuts.html");
226: FileLock fileLock = fo.lock();
227: try {
228: OutputStream outputStream = fo
229: .getOutputStream(fileLock);
230: OutputStreamWriter writer = new OutputStreamWriter(
231: outputStream);
232: writer.write(sb.toString());
233: writer.close();
234: } catch (IOException ex) {
235: ErrorManager.getDefault().notify(ex);
236: } finally {
237: fileLock.releaseLock();
238: }
239: } catch (IOException ex) {
240: ErrorManager.getDefault().notify(ex);
241: }
242: }
243:
244: /**
245: * Writes body of shortcuts table to given StringBuffer.
246: */
247: private static void exportShortcutsToHTML2(KeymapModel keymapModel,
248: StringBuffer sb,
249: Map<String, Map<ShortcutAction, Set<String>>> keymaps) {
250: List<String> categories = new ArrayList<String>(keymapModel
251: .getActionCategories());
252: Collections.<String> sort(categories);
253: Attribs attribs = new Attribs(true);
254: for (String category : categories) {
255:
256: // print category title
257: XMLStorage.generateFolderStart(sb, "tr", attribs, " ");
258: attribs
259: .add("colspan", Integer
260: .toString(keymaps.size() + 1));
261: attribs.add("rowspan", "1");
262: XMLStorage.generateFolderStart(sb, "td", attribs,
263: " ");
264: attribs = new Attribs(true);
265: XMLStorage.generateFolderStart(sb, "h3", attribs,
266: " ");
267: sb.append(category);
268: XMLStorage.generateFolderEnd(sb, "h3", " ");
269: XMLStorage.generateFolderEnd(sb, "td", " ");
270: XMLStorage.generateFolderEnd(sb, "tr", " ");
271:
272: // print body of one category
273: exportShortcutsToHTML3(sb, keymapModel, category, keymaps);
274: }
275: }
276:
277: /**
278: * Writes body of given category.
279: */
280: private static void exportShortcutsToHTML3(StringBuffer sb,
281: KeymapModel keymapModel, String category,
282: Map<String, Map<ShortcutAction, Set<String>>> keymaps) {
283: Set<ShortcutAction> actions = keymapModel.getActions(category);
284:
285: // sort actions
286: Map<String, ShortcutAction> sortedActions = new TreeMap<String, ShortcutAction>();
287: for (ShortcutAction action : actions) {
288: sortedActions.put(action.getDisplayName(), action);
289: }
290:
291: // print actions
292: Attribs attribs = new Attribs(true);
293: for (Map.Entry<String, ShortcutAction> entry : sortedActions
294: .entrySet()) {
295: String actionName = entry.getKey();
296: ShortcutAction action = entry.getValue();
297:
298: // print action name to the first column
299: XMLStorage.generateFolderStart(sb, "tr", attribs, " ");
300: XMLStorage.generateFolderStart(sb, "td", attribs,
301: " ");
302: sb.append(actionName);
303: XMLStorage.generateFolderEnd(sb, "td", " ");
304:
305: for (String profile : keymaps.keySet()) {
306: Map<ShortcutAction, Set<String>> keymap = keymaps
307: .get(profile);
308: Set<String> shortcuts = keymap.get(action);
309:
310: XMLStorage.generateFolderStart(sb, "td", attribs,
311: " ");
312: printShortcuts(shortcuts, sb);
313: XMLStorage.generateFolderEnd(sb, "td", " ");
314: }
315:
316: XMLStorage.generateFolderEnd(sb, "tr", " ");
317: }
318: }
319:
320: private static void printShortcuts(Set<String> shortcuts,
321: StringBuffer sb) {
322: if (shortcuts == null) {
323: sb.append('-');
324: return;
325: }
326: Iterator<String> it = shortcuts.iterator();
327: while (it.hasNext()) {
328: String shortcut = it.next();
329: sb.append(shortcut);
330: if (it.hasNext())
331: sb.append(", ");
332: }
333: }
334:
335: private static void generateLayersXML(LayersBridge layersBridge,
336: Map<String, Map<String, ShortcutAction>> categoryToActions) {
337: Writer fw = null;
338: try {
339: fw = openWriter();
340: if (fw == null)
341: return;
342:
343: StringBuffer sb = XMLStorage.generateHeader();
344: Attribs attribs = new Attribs(true);
345: XMLStorage.generateFolderStart(sb, "filesystem", attribs,
346: "");
347: attribs.add("name", "Keymaps");
348: XMLStorage.generateFolderStart(sb, "folder", attribs,
349: " ");
350: generateShadowsToXML(layersBridge, sb, categoryToActions,
351: " ");
352: XMLStorage.generateFolderEnd(sb, "folder", " ");
353: XMLStorage.generateFolderEnd(sb, "filesystem", "");
354: System.out.println(sb.toString());
355: fw.write(sb.toString());
356: } catch (IOException e) {
357: ErrorManager.getDefault().notify(e);
358: } finally {
359: try {
360: if (fw != null) {
361: fw.flush();
362: fw.close();
363: }
364: } catch (IOException e) {
365: }
366: }
367: }
368:
369: private static void generateEditorXML(
370: Map<ShortcutAction, Set<String>> actionToShortcuts) {
371: Writer fw = null;
372: try {
373: fw = openWriter();
374: if (fw == null)
375: return;
376:
377: StringBuffer sb = XMLStorage.generateHeader();
378: Attribs attribs = new Attribs(true);
379: XMLStorage.generateFolderStart(sb, "bindings", attribs, "");
380:
381: Map<String, Set<String>> sortedMap = new TreeMap<String, Set<String>>();
382: for (ShortcutAction action : actionToShortcuts.keySet()) {
383: sortedMap.put(action.getDisplayName(),
384: actionToShortcuts.get(action));
385: }
386: for (String actionName : sortedMap.keySet()) {
387: Set<String> shortcuts = sortedMap.get(actionName);
388: for (String shortcut : shortcuts) {
389: attribs = new Attribs(true);
390: attribs.add("actionName", actionName);
391: attribs.add("key", shortcut);
392: XMLStorage.generateLeaf(sb, "bind", attribs, " ");
393: }
394: }
395:
396: XMLStorage.generateFolderEnd(sb, "bindings", "");
397: System.out.println(sb.toString());
398: fw.write(sb.toString());
399: } catch (IOException e) {
400: ErrorManager.getDefault().notify(e);
401: } finally {
402: try {
403: if (fw != null) {
404: fw.flush();
405: fw.close();
406: }
407: } catch (IOException e) {
408: }
409: }
410: }
411:
412: private static Map<String, Map<String, ShortcutAction>> resolveNames(
413: Map<String, Set<ShortcutAction>> categoryToActions) {
414: Map<String, Map<String, ShortcutAction>> result = new HashMap<String, Map<String, ShortcutAction>>();
415: for (Map.Entry<String, Set<ShortcutAction>> entry : categoryToActions
416: .entrySet()) {
417: String category = entry.getKey();
418: Set<ShortcutAction> actions = entry.getValue();
419: Map<String, ShortcutAction> actionsMap = new HashMap<String, ShortcutAction>();
420: for (ShortcutAction action : actions) {
421: actionsMap.put(action.getDisplayName(), action);
422: }
423: result.put(category, actionsMap);
424: }
425: return result;
426: }
427:
428: /**
429: * Converts:
430: * Map (String (profile | category) > Map (String (category)) |
431: * ShortcutAction)
432: * to xml.
433: * (String > Map) is represented by folder and
434: * (String > DataObject) by ShadowDO
435: */
436: private static void generateShadowsToXML(LayersBridge layersBridge,
437: StringBuffer sb,
438: Map<String, Map<String, ShortcutAction>> shortcutToAction,
439: String indentation) {
440: Iterator<String> it = shortcutToAction.keySet().iterator();
441: while (it.hasNext()) {
442: String key = it.next();
443: Map<String, ShortcutAction> value = shortcutToAction
444: .get(key);
445: Attribs attribs = new Attribs(true);
446: attribs.add("name", key);
447: XMLStorage.generateFolderStart(sb, "folder", attribs,
448: indentation);
449: generateShadowsToXML2(layersBridge, sb, value, " "
450: + indentation);
451: XMLStorage.generateFolderEnd(sb, "folder", indentation);
452: }
453: }
454:
455: private static void generateShadowsToXML2(
456: LayersBridge layersBridge, StringBuffer sb,
457: Map<String, ShortcutAction> shortcutToAction,
458: String indentation) {
459: Iterator<String> it = shortcutToAction.keySet().iterator();
460: while (it.hasNext()) {
461: String key = it.next();
462: ShortcutAction value = shortcutToAction.get(key);
463:
464: DataObject dob = layersBridge.getDataObject(value);
465: if (dob == null) {
466: System.out.println("no Dataobject " + value);
467: continue;
468: }
469: FileObject fo = dob.getPrimaryFile();
470: Attribs attribs = new Attribs(true);
471: attribs.add("name", key + ".shadow");
472: XMLStorage.generateFolderStart(sb, "file", attribs,
473: indentation);
474: Attribs attribs2 = new Attribs(true);
475: attribs2.add("name", "originalFile");
476: attribs2.add("stringvalue", fo.getPath());
477: XMLStorage.generateLeaf(sb, "attr", attribs2, indentation
478: + " ");
479: XMLStorage.generateFolderEnd(sb, "file", indentation);
480: }
481: }
482:
483: private static Writer openWriter() throws IOException {
484: JFileChooser fileChooser = new JFileChooser();
485: int result = fileChooser.showSaveDialog(WindowManager
486: .getDefault().getMainWindow());
487: if (result != JFileChooser.APPROVE_OPTION)
488: return null;
489: File f = fileChooser.getSelectedFile();
490: return new FileWriter(f);
491: }
492:
493: private static String loc(String key) {
494: return NbBundle.getMessage(ExportShortcutsAction.class, key);
495: }
496: }
|