1 19 20 package org.netbeans.modules.editor.settings.storage; 21 22 import java.util.Arrays ; 23 import java.util.Collection ; 24 import java.util.Collections ; 25 import java.util.HashMap ; 26 import java.util.HashSet ; 27 import java.util.Map ; 28 import java.util.Set ; 29 import java.util.logging.Level ; 30 import java.util.logging.Logger ; 31 import javax.swing.KeyStroke ; 32 import org.netbeans.api.editor.mimelookup.MimePath; 33 import org.netbeans.api.editor.settings.MultiKeyBinding; 34 35 import org.openide.filesystems.FileObject; 36 import org.openide.util.Utilities; 37 import org.openide.xml.XMLUtil; 38 import org.w3c.dom.Document ; 39 import org.w3c.dom.Element ; 40 import org.w3c.dom.Node ; 41 import org.xml.sax.Attributes ; 42 import org.xml.sax.InputSource ; 43 import org.xml.sax.SAXException ; 44 45 46 52 public final class KeyMapsStorage { 53 54 private static final Logger LOG = Logger.getLogger(KeyMapsStorage.class.getName()); 55 56 static final String KEYBINDING_FILE_NAME = "keybindings.xml"; 60 61 static final String DEFAULTS_FOLDER = "Defaults"; 63 private static final String ROOT = "bindings"; private static final String E_BIND = "bind"; private static final String A_ACTION_NAME = "actionName"; private static final String A_KEY = "key"; private static final String A_REMOVE = "remove"; private static final String V_TRUE = "true"; 70 private static final String PUBLIC_ID = "-//NetBeans//DTD Editor KeyBindings settings 1.1//EN"; private static final String SYSTEM_ID = "http://www.netbeans.org/dtds/EditorKeyBindings-1_1.dtd"; 73 private KeyMapsStorage() { 74 } 75 76 78 83 public static Object [] loadKeyMaps ( 84 MimePath mimePath, 85 String profile, 86 boolean defaults 87 ) { 88 if (profile.equals(EditorSettingsImpl.DEFAULT_PROFILE)) profile = null; 90 91 String fileName = defaults ? DEFAULTS_FOLDER + "/" + KEYBINDING_FILE_NAME : KEYBINDING_FILE_NAME; 92 FileObject fo = Utils.getFileObject(mimePath, profile, fileName); 93 if (fo == null) { 94 return new Object [] { 95 Collections.<Collection <KeyStroke >, MultiKeyBinding>emptyMap(), 96 Collections.<Collection <KeyStroke >>emptySet() 97 }; 98 } else { 99 return (Object []) XMLStorage.load(fo, new KeyMapsReader()); 100 } 101 } 102 103 private static class KeyMapsReader extends XMLStorage.Handler { 104 private Map <Collection <KeyStroke >, MultiKeyBinding> keyMap = new HashMap <Collection <KeyStroke >, MultiKeyBinding>(); 105 private Set <Collection <KeyStroke >> removedShortcuts = new HashSet <Collection <KeyStroke >>(); 106 107 public Object getResult() { 108 return new Object [] {keyMap, removedShortcuts}; 109 } 110 111 public void startElement( 112 String uri, 113 String localName, 114 String name, 115 Attributes attributes 116 ) throws SAXException { 117 try { 118 if (name.equals(ROOT)) { 119 121 } else if (name.equals(E_BIND)) { 122 String actionName = attributes.getValue(A_ACTION_NAME); 123 String key = attributes.getValue(A_KEY); 124 125 if (!Utilities.isMac() && 126 isModuleFile() && key != null && key.length() > 0) 127 { 128 int idx = key.indexOf('-'); 132 if (idx != -1 && (key.charAt(0) == 'A' || key.charAt(0) == 'C')) { 133 LOG.warning("The keybinding '" + key + "' for action '" + actionName + "' in " + getProcessedFile().getPath() + " may not work correctly on Mac. " + "Keybindings starting with Alt or Ctrl should " + "be coded with latin capital letters 'O' " + "or 'D' respectively. For details see org.openide.util.Utilities.stringToKey()."); } 139 } 140 141 KeyStroke [] shortcut = Utils.stringToKeyStrokes(key); 142 String remove = attributes.getValue(A_REMOVE); 143 144 if (Boolean.valueOf(remove)) { 145 removedShortcuts.add(Arrays.asList(shortcut)); 146 } else { 147 MultiKeyBinding mkb = new MultiKeyBinding(shortcut, actionName); 148 keyMap.put(Arrays.asList(shortcut), mkb); 149 } 150 } 151 } catch (Exception ex) { 152 LOG.log(Level.WARNING, "Can't parse keybindings file " + getProcessedFile().getPath(), ex); } 154 } 155 156 public InputSource resolveEntity(String pubid, String sysid) { 157 return new InputSource ( 158 new java.io.ByteArrayInputStream (new byte [0]) 159 ); 160 } 161 } 163 164 166 public static void deleteProfile( 167 MimePath mimePath, 168 String profile, 169 boolean defaults 170 ) { 171 if (profile.equals(EditorSettingsImpl.DEFAULT_PROFILE)) { 172 profile = null; 173 } 174 175 String fileName = defaults ? DEFAULTS_FOLDER + "/" + KEYBINDING_FILE_NAME : KEYBINDING_FILE_NAME; 176 Utils.deleteFileObject(mimePath, profile, fileName); 177 } 178 179 181 public static void saveKeyMaps ( 182 MimePath mimePath, 183 String profile, 184 boolean defaults, 185 Collection <MultiKeyBinding> keyMap, Set <Collection <KeyStroke >> removed ) { 188 if (profile.equals(EditorSettingsImpl.DEFAULT_PROFILE)) { 189 profile = null; 190 } 191 192 String fileName = defaults ? DEFAULTS_FOLDER + "/" + KEYBINDING_FILE_NAME : KEYBINDING_FILE_NAME; 193 FileObject fo = Utils.createFileObject(mimePath, profile, fileName); 194 saveKeyMaps (fo, keyMap, removed); 195 } 196 197 private static void saveKeyMaps( 198 FileObject fo, 199 Collection <MultiKeyBinding> keyMap, 200 Set <Collection <KeyStroke >> removed 201 ) { 202 Document doc = XMLUtil.createDocument(ROOT, null, PUBLIC_ID, SYSTEM_ID); 203 Node root = doc.getElementsByTagName(ROOT).item(0); 204 205 for(MultiKeyBinding mkb : keyMap) { 206 Element bind = doc.createElement(E_BIND); 207 root.appendChild(bind); 208 209 bind.setAttribute(A_ACTION_NAME, mkb.getActionName()); 210 bind.setAttribute(A_KEY, Utils.keyStrokesToString(mkb.getKeyStrokeList())); 211 } 212 213 for(Collection <KeyStroke > keyStrokes : removed) { 214 String shortcut = Utils.keyStrokesToString(keyStrokes); 215 Element bind = doc.createElement(E_BIND); 216 root.appendChild(bind); 217 218 bind.setAttribute(A_KEY, shortcut); 219 bind.setAttribute(A_REMOVE, V_TRUE); 220 } 221 222 XMLStorage.save(fo, doc); 223 } 224 } 225 | Popular Tags |