1 /* See license.txt for terms of usage */
  2 
  3 define([
  4     "firebug/lib/lib",
  5     "firebug/lib/object",
  6     "firebug/firebug",
  7     "firebug/chrome/firefox",
  8 ],
  9 function(FBL, Obj, Firebug, Firefox) {
 10 
 11 // ************************************************************************************************
 12 // Constants
 13 
 14 Components.utils.import("resource://gre/modules/Services.jsm");
 15 
 16 var KeyEvent = window.KeyEvent;
 17 
 18 // ************************************************************************************************
 19 
 20 /**
 21  * ShortcutsModel object implements keyboard shortcuts logic.
 22  */
 23 Firebug.ShortcutsModel = Obj.extend(Firebug.Module,
 24 {
 25     dispatchName: "shortcuts",
 26 
 27     initializeUI: function()
 28     {
 29         if (FBTrace.DBG_SHORTCUTS)
 30             FBTrace.sysout("shortcuts.initializeUI; Shortcuts module initialization.");
 31 
 32         this.initShortcuts();
 33     },
 34 
 35     initShortcuts: function()
 36     {
 37         var branch = Services.prefs.getBranch("extensions.firebug.key.shortcut.");
 38         var shortcutNames = branch.getChildList("", {});
 39 
 40         // We need to touch keyset to apply keychanges without restart
 41         this.keysets = [];
 42         this.disabledKeyElements = [];
 43         shortcutNames.forEach(this.initShortcut, this);
 44 
 45         this.keysets.forEach(function(keyset) {
 46             keyset.parentNode.insertBefore(keyset, keyset.nextSibling);
 47         });
 48 
 49         for (var i=0; i<this.disabledKeyElements.length; i++)
 50         {
 51             var elem = this.disabledKeyElements[i];
 52             elem.removeAttribute("disabled");
 53         }
 54 
 55         this.keysets = this.disabledKeyElements = null;
 56     },
 57 
 58     initShortcut: function(element, index, array)
 59     {
 60         var branch = Services.prefs.getBranch("extensions.firebug.key.");
 61         var shortcut = branch.getCharPref("shortcut." + element);
 62         var tokens = shortcut.split(" ");
 63         var key = tokens.pop();
 64         var modifiers = tokens.join(",");
 65 
 66         var keyElem = document.getElementById("key_firebug_" + element);
 67         if (!keyElem)
 68         {
 69             // If key is not defined in xul, add it
 70             keyElem = document.createElement("key");
 71             keyElem.className = "fbOnlyKey";
 72             keyElem.id = "key_firebug_" + element;
 73             keyElem.command = "cmd_firebug_" + element;
 74             document.getElementById("mainKeyset").appendChild(keyElem);
 75         }
 76 
 77         // invalidAttr needed in case default shortcut uses key rather than keycode
 78         var attr = "key";
 79         var invalidAttr = "key";
 80 
 81         // Choose between key or keycode attribute
 82         if (key.length <= 1)
 83         {
 84             invalidAttr = "keycode";
 85         }
 86         else if (KeyEvent["DOM_"+key])
 87         {
 88             attr = "keycode";
 89         }
 90         else
 91         {
 92             // Only set valid keycodes
 93             return;
 94         }
 95 
 96         keyElem.setAttribute("modifiers", modifiers);
 97         keyElem.setAttribute(attr, key);
 98         keyElem.removeAttribute(invalidAttr);
 99 
100         if (this.keysets.indexOf(keyElem.parentNode) == -1)
101             this.keysets.push(keyElem.parentNode);
102 
103         // Modify shortcut for global key, if it exists
104         var keyElem = Firefox.getElementById("key_firebug_" + element);
105         if (!keyElem)
106             return;
107 
108         if (FBTrace.DBG_SHORTCUTS)
109         {
110             FBTrace.sysout("Firebug.ShortcutsModel.initShortcut; global shortcut",
111                 {key: key, modifiers: modifiers});
112         }
113 
114         // Disable existing global shortcuts
115         var selector = "key[" + attr + "='" + key + "'][modifiers='" + modifiers + "']"
116             + ":not([id='key_firebug_" + element + "']):not([disabled='true'])";
117 
118         var existingKeyElements = keyElem.ownerDocument.querySelectorAll(selector);
119         for (var i=existingKeyElements.length-1; i>=0; i--)
120         {
121             var existingKeyElement = existingKeyElements[i];
122             existingKeyElement.setAttribute("disabled", "true");
123             this.disabledKeyElements.push(existingKeyElement);
124         }
125 
126         keyElem.setAttribute("modifiers", modifiers);
127         keyElem.setAttribute(attr, key);
128         keyElem.removeAttribute(invalidAttr);
129 
130         if (this.keysets.indexOf(keyElem.parentNode) == -1)
131             this.keysets.push(keyElem.parentNode);
132     },
133 
134     // UI Commands
135     customizeShortcuts: function()
136     {
137         var args = {
138             FBL: FBL,
139             FBTrace: FBTrace
140         };
141 
142         // Open the "customize shortcuts" dialog. Pass FBL into the XUL window so that
143         // common APIs can be used (e.g. localization).
144         window.openDialog("chrome://firebug/content/firefox/customizeShortcuts.xul", "",
145             "chrome,centerscreen,dialog,modal,resizable=yes", args);
146     }
147 });
148 
149 // ************************************************************************************************
150 // Registration
151 
152 Firebug.registerModule(Firebug.ShortcutsModel);
153 
154 return Firebug.ShortcutsModel;
155 
156 // ************************************************************************************************
157 });
158