hotKeys.js
Go to the documentation of this file.
1 /*
2  *=BEGIN SONGBIRD GPL
3  *
4  * This file is part of the Songbird web player.
5  *
6  * Copyright(c) 2005-2009 POTI, Inc.
7  * http://www.songbirdnest.com
8  *
9  * This file may be licensed under the terms of of the
10  * GNU General Public License Version 2 (the ``GPL'').
11  *
12  * Software distributed under the License is distributed
13  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
14  * express or implied. See the GPL for the specific language
15  * governing rights and limitations.
16  *
17  * You should have received a copy of the GPL along with this
18  * program. If not, go to http://www.gnu.org/licenses/gpl.html
19  * or write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  *=END SONGBIRD GPL
23  */
24 
25 var gHotkeysPane = {
26 
27  _list: null,
28  _remove: null,
29  _set: null,
30  _add: null,
31  _actionlist: null,
32  _hotkey: null,
33  _tool: null,
34  _binding_enabled: null,
35  _enabled: null,
36  _actions: null,
37  _hotkeylabel: null,
38  _actionlabel: null,
39  _disabledHotkeyList: null,
40 
41  init: function init()
42  {
43  var jsLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
44  jsLoader.loadSubScript( "chrome://songbird/content/scripts/messageBox.js", this );
45 
46  window.addEventListener("unload", onHotkeysUnload, true);
47 
48  this._hotkeyService = Cc["@songbirdnest.com/Songbird/HotkeyService;1"]
49  .getService(Ci.sbIHotkeyService);
50 
51  this._binding_enabled = SBDataBindElementAttribute(this._hotkeyService.hotkeysEnabledDRKey, "hotkeys.enabled", "checked", true);
52 
53  this._list = document.getElementById("hotkey.list");
54  this._add = document.getElementById("hotkey.add");
55  this._set = document.getElementById("hotkey.set");
56  this._remove = document.getElementById("hotkey.remove");
57  this._actionlist = document.getElementById("hotkey.actions");
58  this._hotkey = document.getElementById("hotkey.hotkey");
59  this._tool = document.getElementById("hotkey-hotkeytool");
60  this._hotkeylabel = document.getElementById("hotkey.hotkeylabel");
61  this._actionlabel = document.getElementById("hotkey.actionlabel");
62  this._enabled = document.getElementById("hotkeys.enabled");
63  this._disabledHotkeyList = [];
64 
65  this.loadActions();
66  this.loadHotkeys();
67  this.enableDisableElements();
68  },
69 
70  onUnload: function()
71  {
72  window.removeEventListener("unload", onHotkeysUnload, true);
73  this._binding_enabled.unbind();
74  this._binding_enabled = null;
75  },
76 
77  loadActions: function()
78  {
79  var menupopup = this._actionlist.firstChild;
80  while (menupopup.childNodes.length>0) menupopup.removeChild(menupopup.childNodes[0]);
81 
82  var hotkeyActionsComponent = Components.classes["@songbirdnest.com/Songbird/HotkeyActions;1"];
83  if (hotkeyActionsComponent) this._actions = hotkeyActionsComponent.getService(Components.interfaces.sbIHotkeyActions);
84  if (this._actions)
85  {
86  for (var i=0;i<this._actions.bundleCount;i++)
87  {
88  var bundle = this._actions.enumBundle(i);
89  for (var j=0;j<bundle.actionCount;j++)
90  {
91  var actionid = bundle.enumActionID(j);
92  var actiondesc = bundle.enumActionLocaleDescription(j);
93  var item = document.createElement("menuitem");
94  item.actionid = actionid;
95  item.setAttribute("label", actiondesc);
96  menupopup.appendChild(item);
97  }
98  }
99  this._actionlist.selectedItem = menupopup.childNodes[0];
100  }
101  },
102 
103  loadHotkeys: function()
104  {
105  var hotkeyConfigList = this._hotkeyService.getHotkeys();
106  for (var i = 0; i < hotkeyConfigList.length; i++) {
107  // Read hotkey config
108  var hotkeyConfig =
109  hotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
110  if (!this._hotkeyDisabled(hotkeyConfig)) {
111  var keycombo = hotkeyConfig.key;
112  var keydisplay = hotkeyConfig.keyReadable;
113  var actionid = hotkeyConfig.action;
114  var action = this._getLocalizedAction(actionid);
115  // make list items accordingly
116  this._addItem(keycombo, keydisplay, actionid, action, -1);
117  }
118  else {
119  this._disabledHotkeyList.push(hotkeyConfig);
120  }
121  }
122  this.updateButtons();
123  },
124 
125  _hotkeyDisabled: function(hotkeyConfig) {
126  // Hotkey is disabled if it doesn't have an action. This might happen if an
127  // extension sets up a hotkey and is then disabled.
128  var nodes = this._actionlist.firstChild.childNodes;
129  for (var i=0;i<nodes.length;i++) {
130  if (hotkeyConfig.action == nodes[i].actionid)
131  return false;
132  }
133 
134  return true;
135  },
136 
137  _getLocalizedAction: function(actionid)
138  {
139  var nodes = this._actionlist.firstChild.childNodes;
140  for (var i=0;i<nodes.length;i++) {
141  if (actionid == nodes[i].actionid) return nodes[i].getAttribute("label");
142  }
143  return actionid;
144  },
145 
146  _addItem: function(keycombo, keydisplay, actionid, action, replace)
147  {
148  this._tool.setHotkey(keycombo, keydisplay);
149  keydisplay = this._tool.getHotkey(1);
150 
151  // if an index to replace was specified, figure out the corresponding item to use as a marker for insertBefore
152  var before = (replace == -1) ? null : this._list.getItemAtIndex(replace);
153  // make list item
154  var listitem = document.createElement("listitem");
155  listitem.keycombo = keycombo;
156  listitem.actionid = actionid;
157  var listcell_action = document.createElement("listcell");
158  listcell_action.setAttribute("label", action);
159  var listcell_keydisplay = document.createElement("listcell");
160  listcell_keydisplay.setAttribute("label", keydisplay.toUpperCase());
161  listitem.appendChild(listcell_action);
162  listitem.appendChild(listcell_keydisplay);
163  if (before) {
164  // insert the item at the correct spot
165  this._list.insertBefore(listitem, before);
166  // and remove the item we were supposed to replace
167  this._list.removeChild(before);
168  } else {
169  // append at the end of the list (replace was -1)
170  this._list.appendChild(listitem);
171  }
172  },
173 
174  saveHotkeys: function()
175  {
176  // Set all hotkeys, extract them from the list itself
177  var hotkeyConfigList = Cc["@songbirdnest.com/moz/xpcom/threadsafe-array;1"]
178  .createInstance(Ci.nsIMutableArray);
179  var n = this._list.getRowCount();
180  for (var i=0;i<n;i++)
181  {
182  var hotkeyConfig = Cc["@songbirdnest.com/Songbird/HotkeyConfiguration;1"]
183  .createInstance(Ci.sbIHotkeyConfiguration);
184  var item = this._list.getItemAtIndex(i);
185  var keycombo = item.keycombo;
186  var actionid = item.actionid;
187  var actioncell = item.firstChild;
188  var keydisplaycell = actioncell.nextSibling;
189  var keydisplay = keydisplaycell.getAttribute("label");
190  hotkeyConfig.key = keycombo;
191  hotkeyConfig.keyReadable = keydisplay;
192  hotkeyConfig.action = actionid;
193  if (!this._configListContainsKey(hotkeyConfigList, hotkeyConfig.key))
194  hotkeyConfigList.appendElement(hotkeyConfig, false);
195  }
196 
197  // Add any disabled hotkeys. This ensures that if an extension adds a
198  // hotkey and is then disabled, its hotkey setting is preserved when the
199  // extension is re-enabled. If the user reassigns the disabled hotkey in
200  // the UI, it will not be added here.
201  if (this._disabledHotkeyList) {
202  for (var i = 0; i < this._disabledHotkeyList.length; i++) {
203  if (!this._configListContainsKey(hotkeyConfigList, hotkeyConfig.key))
204  hotkeyConfigList.appendElement(this._disabledHotkeyList[i], false);
205  }
206  }
207 
208  this._hotkeyService.setHotkeys(hotkeyConfigList);
209  },
210 
211  _configListContainsKey: function(aHotkeyConfigList, aKey) {
212  for (var i = 0; i < aHotkeyConfigList.length; i++) {
213  var hotkeyConfig =
214  aHotkeyConfigList.queryElementAt(i, Ci.sbIHotkeyConfiguration);
215  if (hotkeyConfig.key == aKey)
216  return true;
217  }
218 
219  return false;
220  },
221 
222  onSelectHotkey: function()
223  {
224  this.updateButtons();
225  var selected = this._list.selectedIndex;
226  if (selected >= 0) {
227  var item = this._list.getItemAtIndex(selected);
228  var actioncell = item.firstChild;
229  var keydisplaycell = actioncell.nextSibling;
230  // load action in menulist
231  var nodes = this._actionlist.firstChild.childNodes;
232  var actionstr = actioncell.getAttribute("label");
233  for (var i=0;i<nodes.length;i++) {
234  if (nodes[i].getAttribute("label") == actionstr) {
235  this._actionlist.selectedItem = nodes[i]
236  break;
237  }
238  }
239  // load hotkey in hotkey control
240  this._hotkey.setHotkey(item.keycombo, keydisplaycell.getAttribute("label"));
241  }
242  },
243 
244  updateButtons: function()
245  {
246  // disable set & remove when no item is selected
247  var disabled = (this._list.selectedIndex== -1);
248  var alldisabled = !this._hotkeyService.hotkeysEnabled;
249  this._remove.setAttribute("disabled", (disabled||alldisabled));
250  this._set.setAttribute("disabled", (disabled||alldisabled));
251  this._add.setAttribute("disabled", alldisabled);
252  },
253 
254  addHotkey: function()
255  {
256  // add the hotkey to the list
257  var keycombo = this._hotkey.getHotkey(false);
258  if (this._checkComboExists(keycombo, -1)) return;
259  var keydisplay = this._hotkey.getHotkey(true);
260  var action = this._actionlist.selectedItem.getAttribute("label");
261  var actionid = this._actionlist.selectedItem.actionid;
262  if (action == "" || keycombo == "" || keydisplay == "" || actionid == "") return;
263  this._addItem(keycombo, keydisplay, actionid, action, -1);
264  // select the last (newly added) item
265  this._list.selectedIndex = this._list.getRowCount()-1;
266  this.saveHotkeys();
267  },
268 
269  setHotkey: function()
270  {
271  // change the hotkey item that's currently selected
272  var selected = this._list.selectedIndex;
273  var keycombo = this._hotkey.getHotkey(false);
274  if (this._checkComboExists(keycombo, selected)) return;
275  var keydisplay = this._hotkey.getHotkey(true);
276  var action = this._actionlist.selectedItem.getAttribute("label");
277  var actionid = this._actionlist.selectedItem.actionid;
278  if (action == "" || keycombo == "" || keydisplay == "") return;
279  this._addItem(keycombo, keydisplay, actionid, action, selected);
280  // reselect the item after it's been changed
281  this._list.selectedIndex = selected;
282  this.saveHotkeys();
283  },
284 
285  _checkComboExists: function(keycombo, ignoreentry)
286  {
287  // checks wether the key combination already exists
288  for (var i=0;i<this._list.getRowCount();i++)
289  {
290  if (i == ignoreentry) continue;
291  var item = this._list.getItemAtIndex(i);
292  if (item.keycombo == keycombo) {
293  this.sbMessageBox_strings("hotkeys.hotkeyexists.title", "hotkeys.hotkeyexists.msg", "Hotkey", "This hotkey is already taken", false);
294  return true;
295  }
296  }
297  return false;
298  },
299 
300  removeHotkey: function()
301  {
302  // remove the selected item from the list
303  var index = this._list.selectedIndex;
304  var item = this._list.getItemAtIndex(index);
305  this._list.removeChild(item);
306  // select the next item, or the previous one if that was the last
307  if (index >= this._list.getRowCount()) index = this._list.getRowCount()-1;
308  this._list.selectedIndex = index;
309  this.saveHotkeys();
310  },
311 
312  onEnableDisable: function()
313  {
314  this._hotkeyService.hotkeysEnabled =
315  (this._enabled.getAttribute("checked") == "true");
316  this.enableDisableElements();
317  },
318 
319  enableDisableElements: function() {
320  var enabled = this._hotkeyService.hotkeysEnabled;
321  if (enabled) {
322  this._actionlist.removeAttribute("disabled");
323  this._list.removeAttribute("disabled");
324  this._hotkey.removeAttribute("disabled");
325  this._hotkeylabel.removeAttribute("disabled");
326  this._actionlabel.removeAttribute("disabled");
327  this._list.setAttribute("style", "opacity: 1 !important;");
328  this._hotkey.setAttribute("style", "opacity: 1 !important;");
329  } else {
330  this._actionlist.setAttribute("disabled", "true");
331  this._list.setAttribute("disabled", "true");
332  this._list.setAttribute("disabled", "true");
333  this._hotkey.setAttribute("disabled", "true");
334  this._hotkeylabel.setAttribute("disabled", "true");
335  this._actionlabel.setAttribute("disabled", "true");
336  this._list.setAttribute("style", "opacity: 0.5 !important;");
337  this._hotkey.setAttribute("style", "opacity: 0.5 !important;");
338  }
339  this.updateButtons();
340  }
341 };
342 
343 function onHotkeysUnload()
344 {
345  gHotkeysPane.onUnload();
346 }
347 
function onHotkeysUnload()
Definition: hotKeys.js:343
const Cc
function SBDataBindElementAttribute(aKey, aElement, aAttribute, aIsBool, aIsNot, aEvalString)
Create a DataRemote and bind an Element's attribute to the data. This method creates a DataRemote ass...
function sbMessageBox_strings(titlestring, msgstring, deftitle, defmsg, wantcancel, notmodal)
Definition: messageBox.js:50
let window
var gHotkeysPane
Definition: hotKeys.js:25
_window init
Definition: FeedWriter.js:1144
var bundle
return null
Definition: FeedWriter.js:1143
return aWindow document documentElement getAttribute(aAttribute)||dimension
const Ci
function onUnload()
onUnload - called when the cover preview window unloads.
Definition: coverPreview.js:36
_getSelectedPageStyle s i