27 if (typeof(
Ci) ==
"undefined")
28 var
Ci = Components.interfaces;
29 if (typeof(
Cc) ==
"undefined")
30 var
Cc = Components.classes;
31 if (typeof(
Cr) ==
"undefined")
32 var
Cr = Components.results;
33 if (typeof(
Cu) ==
"undefined")
34 var
Cu = Components.utils;
36 Cu.import(
"resource://app/jsmodules/ArrayConverter.jsm");
37 Cu.import(
"resource://app/jsmodules/sbCoverHelper.jsm");
38 Cu.import(
"resource://app/jsmodules/SBJobUtils.jsm");
39 Cu.import(
"resource://app/jsmodules/sbLibraryUtils.jsm");
40 Cu.import(
"resource://app/jsmodules/sbProperties.jsm");
41 Cu.import(
"resource://app/jsmodules/StringUtils.jsm");
42 Cu.import(
"resource://gre/modules/XPCOMUtils.jsm");
59 this._propertyListeners = {};
60 this._selectionListeners = [];
61 this._properties = {};
65 _propertyManager: Cc[
"@songbirdnest.com/Songbird/Properties/PropertyManager;1"]
66 .getService(Ci.sbIPropertyManager),
86 _writableItemCount:
null,
89 _propertyListeners:
null,
92 _selectionListeners:
null,
98 setSelection:
function TrackEditorState_setSelection(mediaListSelection) {
99 this._selectedItems = [];
100 var items = mediaListSelection.selectedIndexedMediaItems;
101 while (items.hasMoreElements()) {
102 var item = items.getNext()
103 .QueryInterface(Ci.sbIIndexedMediaItem)
105 this._selectedItems.push(item);
108 this._properties = {};
109 this._writableItemCount =
null;
111 this._notifySelectionListeners();
112 this._notifyPropertyListeners();
120 return this.writableItemCount == 0;
126 get writableItemCount() {
127 if (this._writableItemCount ==
null) {
128 this._writableItemCount = 0;
129 if (this._selectedItems && this._selectedItems.length > 0) {
132 for each (var item
in this._selectedItems) {
134 this._writableItemCount++;
139 return this._writableItemCount;
146 get selectedItems() {
147 return this._selectedItems;
153 getPropertyValue:
function(property) {
154 this._ensurePropertyData(property);
155 return this._properties[property].value;
162 resetPropertyValue:
function(property) {
163 if (property in this._properties) {
164 delete this._properties[property];
166 this._ensurePropertyData(property);
167 this._notifyPropertyListeners(property);
177 hasMultipleValuesForProperty:
function(property) {
178 this._ensurePropertyData(property);
179 return this._properties[property].hasMultiple;
186 setPropertyValue:
function(property,
value) {
187 this._ensurePropertyData(property);
188 this._properties[property].value =
value;
189 this._properties[property].edited =
true;
192 this._properties[property].hasMultiple =
false;
197 this.validatePropertyValue(property);
204 isPropertyEdited:
function(property) {
205 this._ensurePropertyData(property);
206 return this._properties[property].edited;
215 isPropertyEnabled:
function(property) {
216 this._ensurePropertyData(property);
217 return this._properties[property].enabled;
225 setPropertyEnabled:
function(property, enabled) {
226 this._ensurePropertyData(property);
227 this._properties[property].enabled = enabled;
228 this._notifyPropertyListeners(property);
236 isPropertyInvalidated:
function(property) {
237 this._ensurePropertyData(property);
238 return this._properties[property].knownInvalid;
246 validatePropertyValue:
function(property) {
247 var needsNotification =
true;
249 this._ensurePropertyData(property);
252 if (this._properties[property].edited) {
254 var
value = this._properties[property].value;
259 var valid = this._properties[property].propInfo.validate(value);
260 this._properties[property].knownInvalid = !valid;
267 if(property == SBProperties.totalTracks ||
268 property == SBProperties.trackNumber) {
270 this._properties[SBProperties.totalTracks].knownInvalid =
271 !isNaN(this._properties[SBProperties.totalTracks].value) &&
272 !isNaN(this._properties[SBProperties.trackNumber].value) &&
273 (parseInt(this._properties[SBProperties.totalTracks].value) <
274 parseInt(this._properties[SBProperties.trackNumber].value))
276 this._properties[SBProperties.trackNumber].knownInvalid =
277 !isNaN(this._properties[SBProperties.totalTracks].value) &&
278 !isNaN(this._properties[SBProperties.trackNumber].value) &&
279 (parseInt(this._properties[SBProperties.trackNumber].value) >
280 parseInt(this._properties[SBProperties.totalTracks].value))
282 needsNotification =
false;
284 this._notifyPropertyListeners(SBProperties.totalTracks);
285 this._notifyPropertyListeners(SBProperties.trackNumber);
288 if(property == SBProperties.totalDiscs ||
289 property == SBProperties.discNumber) {
291 this._properties[SBProperties.totalDiscs].knownInvalid =
292 !isNaN(this._properties[SBProperties.totalDiscs].value) &&
293 !isNaN(this._properties[SBProperties.discNumber].value) &&
294 (parseInt(this._properties[SBProperties.discNumber].value) >
295 parseInt(this._properties[SBProperties.totalDiscs].value));
297 this._properties[SBProperties.discNumber].knownInvalid =
298 !isNaN(this._properties[SBProperties.totalDiscs].value) &&
299 !isNaN(this._properties[SBProperties.discNumber].value) &&
300 (parseInt(this._properties[SBProperties.totalDiscs].value) <
301 parseInt(this._properties[SBProperties.discNumber].value));
303 needsNotification =
false;
305 this._notifyPropertyListeners(SBProperties.totalDiscs);
306 this._notifyPropertyListeners(SBProperties.discNumber);
311 if(needsNotification) {
312 this._notifyPropertyListeners(property);
322 isKnownInvalid:
function() {
323 for (var propertyName in this._properties) {
324 if (this._properties[propertyName].knownInvalid &&
325 this._properties[propertyName].enabled) {
337 getEnabledProperties:
function() {
338 var enabledList = [];
339 for (var propertyName in this._properties) {
340 if (this._properties[propertyName].enabled) {
341 enabledList.push(propertyName);
351 _ensurePropertyData:
function TrackEditorState__ensurePropertyData(property) {
353 if (property in this._properties) {
358 this._properties[property] = {
364 propInfo: this._propertyManager.getPropertyInfo(property),
369 if (this._selectedItems && this._selectedItems.length > 0) {
370 var value = this._selectedItems[0].getProperty(property);
372 if (property == SBProperties.primaryImageURL) {
374 var MAX_ITEMS_TO_CHECK = 30;
375 var selectedItems =
TrackEditor.state.selectedItems;
376 var numToCheck = Math.min(MAX_ITEMS_TO_CHECK, selectedItems.length);
379 for (var
i = 0;
i < numToCheck;
i++) {
380 value = selectedItems[
i].getProperty(property);
386 if (seedValue != value) {
393 if (this._selectedItems.length > 1) {
396 for each (var item
in this._selectedItems) {
397 if (value != item.getProperty(property)) {
398 this._properties[property].hasMultiple =
true;
408 if (property == SBProperties.primaryImageURL) {
411 else if (this._properties[property].hasMultiple) {
417 value = this._properties[property].propInfo.format(value);
420 Components.utils.reportError(
"TrackEditor::getPropertyValue("+property+
") - "+value+
": " + e +
"\n");
429 this._properties[property].value =
value;
435 if (this._properties[property].hasMultiple) {
436 this._properties[property].edited =
true;
437 this._properties[property].originalValue =
null;
439 this._properties[property].originalValue =
value;
450 addPropertyListener:
function(property,
listener) {
451 if (!(
"onTrackEditorPropertyChange" in
listener)) {
452 throw new Error(
"Listener must provide a onTrackEditorPropertyChange function");
455 if (!(property in this._propertyListeners)) {
456 this._propertyListeners[property] = [
listener];
458 this._propertyListeners[property].push(listener);
465 removePropertyListener:
function(property,
listener) {
466 if (property in this._propertyListeners) {
467 var
array = this._propertyListeners[property];
468 var index = array.indexOf(listener);
470 array.splice(index,1);
481 addSelectionListener:
function(
listener) {
482 if (!(
"onTrackEditorSelectionChange" in listener)) {
483 throw new Error(
"Listener must provide a onTrackEditorSelectionChange function");
485 this._selectionListeners.push(listener);
491 removeSelectionListener:
function(
listener) {
492 var index = this._selectionListeners.indexOf(listener);
494 this._selectionListeners.splice(index,1);
502 _notifyPropertyListeners:
function TrackEditorState__notifyPropertyListeners(property) {
504 if (property ==
null) {
505 for each (var listenerArray
in this._propertyListeners) {
506 for each (var listener
in listenerArray) {
507 listener.onTrackEditorPropertyChange(property);
513 var listeners = this._propertyListeners[property];
515 for each (var listener
in listeners) {
516 listener.onTrackEditorPropertyChange(property);
521 if (property !=
"all") {
522 var listeners = this._propertyListeners[
"all"];
524 for each (var listener
in listeners) {
525 listener.onTrackEditorPropertyChange(property);
535 _notifySelectionListeners:
function TrackEditorState__notifySelectionListeners() {
536 for each (var listener
in this._selectionListeners) {
537 listener.onTrackEditorSelectionChange();
function TrackEditorState()
Javascript wrappers for common library tasks.
_getSelectedPageStyle s i