pfServicePane.js
Go to the documentation of this file.
1 
5 const Cc = Components.classes;
6 const Ci = Components.interfaces;
7 const Cr = Components.results;
8 
9 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
10 
11 Components.utils.import("resource://app/jsmodules/sbProperties.jsm");
12 Components.utils.import("resource://app/jsmodules/sbLibraryUtils.jsm");
13 Components.utils.import("resource://app/jsmodules/ArrayConverter.jsm");
14 Components.utils.import("resource://app/jsmodules/DropHelper.jsm");
15 Components.utils.import("resource://app/jsmodules/StringUtils.jsm");
16 Components.utils.import("resource://app/jsmodules/WindowUtils.jsm");
17 
18 const CONTRACTID = "@rsjtdrjgfuzkfg.com/servicepane/folders;1";
19 
20 const URN_PREFIX_FOLDER = 'urn:folder:';
21 
22 const LSP = 'http://songbirdnest.com/rdf/library-servicepane#';
23 const SP='http://songbirdnest.com/rdf/servicepane#';
24 
25 const TYPE_X_SB_TRANSFER_MEDIA_LIST = "application/x-sb-transfer-media-list";
26 const TYPE_X_PF_TRANSFER_FOLDER = "application/x-pf-transfer-folder";
27 
33 function pfServicePane() {
34  this._servicePane = null;
35 }
36 
38 // nsISupports / XPCOM //
40 
41 pfServicePane.prototype.QueryInterface =
42  XPCOMUtils.generateQI([Ci.nsIObserver,
43  Ci.sbIServicePaneModule,
44  Ci.sbIServicePaneService,
45  Ci.nsIWindowMediatorListener]);
46 
47 pfServicePane.prototype.classID =
48  Components.ID("{12382b5a-e782-4de5-8b34-a26b82cdeeb8}");
49 pfServicePane.prototype.classDescription =
50  "Playlist Folder AddOn Service Pane Service";
51 pfServicePane.prototype.contractID =
52  CONTRACTID;
53 pfServicePane.prototype._xpcom_categories = [{
54  category: 'service-pane',
55  entry: 'folders',
57 }];
58 
59 
61 // sbIServicePaneModule //
63 
64 pfServicePane.prototype.servicePaneInit =
65 function pfServicePane_servicePaneInit(sps) {
66 
67  // keep track of the service pane service
68  this._servicePane = sps;
69 
70  // connect to the global controllers of this AddOn
71  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
72  getService(Components.interfaces.nsIWindowMediator);
73  var mainWindow = wm.getMostRecentWindow("Songbird:Main");
74  if (mainWindow)
75  this._playlistfolders = mainWindow.playlistfolders;
76  else{
77  Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService).
78  addObserver(this, 'songbird-main-window-presented', false);
79  }
80 }
81 
82 pfServicePane.prototype.shutdown =
83 function pfServicePane_shutdown() {}
84 
85 pfServicePane.prototype.fillContextMenu =
86 function pfServicePane_fillContextMenu(aNode, aContextMenu, aParentWindow) {
87  var libraryMgr = Cc["@songbirdnest.com/Songbird/library/Manager;1"]
88  .getService(Ci.sbILibraryManager);
89 
90  // the playlists folder and the local library node get the "New Folder" item
91  if ((aNode.id == 'SB:Playlists') ||
92  (aNode.id.split('urn:library:' + libraryMgr.mainLibrary.guid).length > 1) ||
93  (aNode.getAttributeNS(LSP, 'ListCustomType') == 'local')) {
94  this.fillNewItemMenu(aNode, aContextMenu, aParentWindow);
95  }
96 
97  // the folders get rename and delete entries
98  if (aNode.id.split(URN_PREFIX_FOLDER).length > 1){
99  this.fillFolderMenu(aNode, aContextMenu, aParentWindow);
100  }
101 }
102 
103 pfServicePane.prototype.fillNewItemMenu =
104 function pfServicePane_fillNewItemMenu(aNode, aContextMenu, aParentWindow) {
105  var sbSvc = Cc["@mozilla.org/intl/stringbundle;1"].
106  getService(Ci.nsIStringBundleService);
107  var stringBundle = sbSvc.createBundle("chrome://songbird/locale/songbird." +
108  "properties");
109 
110  // Add the new folder Button
111  var menuitem = aContextMenu.ownerDocument.createElement("menuitem");
112  menuitem.setAttribute("id", "menuitem_file_folder");
113  menuitem.setAttribute("class", "menuitem-iconic");
114  menuitem.setAttribute("label", stringBundle.
115  GetStringFromName("menu.servicepane." +
116  "file.folder"));
117  menuitem.setAttribute("accesskey", stringBundle.
118  GetStringFromName("menu." +
119  "servicepane." +
120  "file.folder." +
121  "accesskey"));
122  menuitem.setAttribute("oncommand", "playlistfolders.servicepane." +
123  "newFolder();");
124  aContextMenu.appendChild(menuitem);
125 }
126 
127 pfServicePane.prototype.fillFolderMenu =
128 function pfServicePane_fillFolderMenu(aNode, aContextMenu, aParentWindow) {
129  var sbSvc = Cc["@mozilla.org/intl/stringbundle;1"].
130  getService(Ci.nsIStringBundleService);
131  var stringBundle = sbSvc.createBundle("chrome://songbird/locale/songbird." +
132  "properties");
133 
134  // Add the delete folder button
135  var menuitem = aContextMenu.ownerDocument.createElement("menuitem");
136  menuitem.setAttribute("id", "menuitem_folder_delete");
137  menuitem.setAttribute("class", "menuitem-iconic");
138  menuitem.setAttribute("label", stringBundle.
139  GetStringFromName("command.playlist.remove"));
140  menuitem.setAttribute("oncommand", "playlistfolders.servicepane." +
141  "deleteFolder('" + aNode.id + "');");
142  aContextMenu.appendChild(menuitem);
143 
144  // Add the rename folder button
145  menuitem = aContextMenu.ownerDocument.createElement("menuitem");
146  menuitem.setAttribute("id", "menuitem_folder_rename");
147  menuitem.setAttribute("class", "menuitem-iconic");
148  menuitem.setAttribute("label", stringBundle.
149  GetStringFromName("command.playlist.rename"));
150  menuitem.setAttribute("oncommand", "gServicePane.startEditingNode(document." +
151  "getElementById('" + aNode.id + "').nodeData);");
152  aContextMenu.appendChild(menuitem);
153 }
154 
155 pfServicePane.prototype.onSelectionChanged =
156 function pfServicePane_onSelectionChanged(aNode, aContainer, aParentWindow) {
157 }
158 
159 pfServicePane.prototype._canDropReorder =
160 function pfServicePane__canDropReorder(aNode, aDragSession, aOrientation) {
161  // see if we can handle the drag and drop based on node properties
162  let types = [];
163  if (aOrientation == 0) {
164  // drop in
165  if (aNode.dndAcceptIn) {
166  types = aNode.dndAcceptIn.split(',');
167  }
168  } else {
169  // drop near
170  if (aNode.dndAcceptNear) {
171  types = aNode.dndAcceptNear.split(',');
172  }
173  }
174  for each (let type in types) {
175  if (aDragSession.isDataFlavorSupported(type)) {
176  return type;
177  }
178  }
179  return null;
180 }
181 
182 pfServicePane.prototype.canDrop =
183 function pfServicePane_canDrop(aNode, aDragSession, aOrientation, aWindow) {
184  // Accept Folders, if they are no parent folders
185  if (aDragSession.isDataFlavorSupported(TYPE_X_PF_TRANSFER_FOLDER)){
186  let transferable = Cc["@mozilla.org/widget/transferable;1"].
187  createInstance(Ci.nsITransferable);
188  transferable.addDataFlavor(TYPE_X_PF_TRANSFER_FOLDER);
189  aDragSession.getData(transferable, 0);
190  let data = {};
191  transferable.getTransferData(TYPE_X_PF_TRANSFER_FOLDER, data, {});
192  data = data.value.QueryInterface(Ci.nsISupportsString).data;
193  var isparent = function(node, parentid){
194  if (node.id == parentid){
195  return true;
196  }
197  if (node.parentNode.id.split(URN_PREFIX_FOLDER).length > 1){
198  if (isparent(node.parentNode, parentid)){
199  return true;
200  }
201  }
202  return false;
203  };
204  if (isparent(aNode, data)){
205  return false;
206  }
207  return true;
208  }
209 
210  // Use Drag and Drop Attributes
211  if (this._canDropReorder(aNode, aDragSession, aOrientation))
212  return true;
213 
214  // Accept playlists
215  return aDragSession.isDataFlavorSupported(TYPE_X_SB_TRANSFER_MEDIA_LIST);
216 }
217 
218 pfServicePane.prototype.onDrop =
219 function pfServicePane_onDrop(aNode, aDragSession, aOrientation, aWindow) {
220  if (aDragSession.isDataFlavorSupported(TYPE_X_PF_TRANSFER_FOLDER)){
221  // Get the folder's Node's ID
222  let transferable = Cc["@mozilla.org/widget/transferable;1"].
223  createInstance(Ci.nsITransferable);
224  transferable.addDataFlavor(TYPE_X_PF_TRANSFER_FOLDER);
225  aDragSession.getData(transferable, 0);
226  let data = {};
227  transferable.getTransferData(TYPE_X_PF_TRANSFER_FOLDER, data, {});
228  data = data.value.QueryInterface(Ci.nsISupportsString).data;
229 
230  if (aOrientation == 0)
231  // Move Folder into aNode
232  this._playlistfolders.servicepane.
233  moveFolder(data,
234  aNode,
235  null);
236  if (aOrientation > 0)
237  // Move Folder under aNode
238  this._playlistfolders.servicepane.
239  moveFolder(data,
240  aNode.parentNode,
241  aNode.nextSibling);
242  if (aOrientation < 0)
243  // Move Folder before aNode
244  this._playlistfolders.servicepane.
245  moveFolder(data,
246  aNode.parentNode,
247  aNode);
248  } else if (aDragSession.isDataFlavorSupported(TYPE_X_SB_TRANSFER_MEDIA_LIST)){
249  // Get the playlist's id
250  var draggedList = DNDUtils.
251  getInternalTransferDataForFlavour(aDragSession,
253  Ci.sbIMediaListTransferContext);
254  var pguid = draggedList.list.guid;
255 
256  if (aOrientation == 0)
257  // Move Folder into aNode
258  this._playlistfolders.servicepane.
259  movePlaylist(pguid,
260  aNode,
261  null);
262  if (aOrientation > 0)
263  // Move Folder under aNode
264  this._playlistfolders.servicepane.
265  movePlaylist(pguid,
266  aNode.parentNode,
267  aNode.nextSibling);
268  if (aOrientation < 0)
269  // Move Folder before aNode
270  this._playlistfolders.servicepane.
271  movePlaylist(pguid,
272  aNode.parentNode,
273  aNode);
274  }
275 }
276 
277 pfServicePane.prototype.onDragGesture =
278 function pfServicePane_onDragGesture(aNode, aDataTransfer) {
279  // Ignore non-folders
280  if (aNode.id.split(URN_PREFIX_FOLDER).length <= 1)
281  return false;
282  // Do not interfere with playlist draggings
283  if (aDataTransfer.getData(TYPE_X_SB_TRANSFER_MEDIA_LIST))
284  return false;
285  // Do not drag more than one folder at a time
286  if (aDataTransfer.getData(TYPE_X_PF_TRANSFER_FOLDER))
287  return false;
288 
289  aDataTransfer.setData(TYPE_X_PF_TRANSFER_FOLDER, aNode.id);
290  return true;
291 }
292 
293 
297 pfServicePane.prototype.onBeforeRename =
298 function pfServicePane_onBeforeRename(aNode) {
299 }
300 
304 pfServicePane.prototype.onRename =
305 function pfServicePane_onRename(aNode, aNewName) {
306  if (aNode && aNewName) {
307  this._playlistfolders.servicepane.renameFolder(aNode, aNewName);
308  }
309 }
310 
311 
313 // nsIObserver //
315 
316 pfServicePane.prototype.observe =
317 function pfServicePane_observe(subject, topic, data) {
318  // Link
319  if (topic == 'songbird-main-window-presented') {
320  // connect to the global controllers of this AddOn
321  var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
322  getService(Components.interfaces.nsIWindowMediator);
323  var mainWindow = wm.getMostRecentWindow("Songbird:Main");
324  this._playlistfolders = mainWindow.playlistfolders;
325  // We no longer need to observe
326  Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService).
327  removeObserver(this, 'songbird-main-window-presented');
328  }
329 }
330 
332 // XPCOM //
334 
335 var NSGetModule = XPCOMUtils.generateNSGetModule([pfServicePane]);
classDescription entry
Definition: FeedWriter.js:1427
const Ci
Definition: pfServicePane.js:6
prefs removeObserver(PREF_SELECTED_ACTION, this)
function pfServicePane()
const LSP
var DNDUtils
Definition: DropHelper.jsm:80
sidebarFactory createInstance
Definition: nsSidebar.js:351
const char * types
const Cr
Definition: pfServicePane.js:7
const URN_PREFIX_FOLDER
getService(Ci.sbIFaceplateManager)
const CONTRACTID
const TYPE_X_SB_TRANSFER_MEDIA_LIST
Definition: DropHelper.jsm:413
historySvc addObserver(this, false)
return null
Definition: FeedWriter.js:1143
const Cc
Definition: pfServicePane.js:5
let node
countRef value
Definition: FeedWriter.js:1423
const TYPE_X_PF_TRANSFER_FOLDER
observe topic
Definition: FeedWriter.js:1326
observe data
Definition: FeedWriter.js:1329