diff --git a/chrome/chromeFiles/content/scholar/collectionTreeView.js b/chrome/chromeFiles/content/scholar/collectionTreeView.js index ebd4f12f2..b1449d2ab 100644 --- a/chrome/chromeFiles/content/scholar/collectionTreeView.js +++ b/chrome/chromeFiles/content/scholar/collectionTreeView.js @@ -1,3 +1,14 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// CollectionTreeView +/// -- handles the link between an individual tree and the data layer +/// -- displays only collections, in a hierarchy (no items) +/// +//////////////////////////////////////////////////////////////////////////////// + +/* + * Constructor the the CollectionTreeView object + */ Scholar.CollectionTreeView = function() { this._treebox = null; @@ -6,6 +17,9 @@ Scholar.CollectionTreeView = function() this._unregisterID = Scholar.Notifier.registerColumnTree(this); } +/* + * Called by the tree itself + */ Scholar.CollectionTreeView.prototype.setTree = function(treebox) { if(this._treebox) @@ -13,6 +27,10 @@ Scholar.CollectionTreeView.prototype.setTree = function(treebox) this._treebox = treebox; } +/* + * Reload the rows from the data access methods + * (doesn't call the tree.invalidate methods, etc.) + */ Scholar.CollectionTreeView.prototype.refresh = function() { this._dataItems = new Array(); @@ -27,7 +45,7 @@ Scholar.CollectionTreeView.prototype.refresh = function() } /* - * Is called by Scholar.Notifier on any changes to the data layer + * Called by Scholar.Notifier on any changes to collections in the data layer */ Scholar.CollectionTreeView.prototype.notify = function(action, type, ids) { @@ -102,13 +120,20 @@ Scholar.CollectionTreeView.prototype.notify = function(action, type, ids) } /* - * Unregisters itself from Scholar.Notifier (called on window close) + * Unregisters view from Scholar.Notifier (called on window close) */ Scholar.CollectionTreeView.prototype.unregister = function() { Scholar.Notifier.unregisterColumnTree(this._unregisterID); } +//////////////////////////////////////////////////////////////////////////////// +/// +/// nsITreeView functions +/// http://www.xulplanet.com/references/xpcomref/ifaces/nsITreeView.html +/// +//////////////////////////////////////////////////////////////////////////////// + Scholar.CollectionTreeView.prototype.getCellText = function(row, column) { var obj = this._getItemAtRow(row); @@ -137,6 +162,8 @@ Scholar.CollectionTreeView.prototype.isContainerOpen = function(row) Scholar.CollectionTreeView.prototype.isContainerEmpty = function(row) { + //NOTE: this returns true if the collection has no child collections + var itemGroup = this._getItemAtRow(row); if(itemGroup.isCollection()) return !itemGroup.ref.hasChildCollections(); @@ -170,6 +197,9 @@ Scholar.CollectionTreeView.prototype.hasNextSibling = function(row, afterIndex) } } +/* + * Opens/closes the specified row + */ Scholar.CollectionTreeView.prototype.toggleOpenState = function(row) { var count = 0; //used to tell the tree how many rows were added/removed @@ -202,6 +232,15 @@ Scholar.CollectionTreeView.prototype.toggleOpenState = function(row) this._refreshHashMap(); } +//////////////////////////////////////////////////////////////////////////////// +/// +/// Additional functions for managing data in the tree +/// +//////////////////////////////////////////////////////////////////////////////// + +/* + * Delete the selection + */ Scholar.CollectionTreeView.prototype.deleteSelection = function() { if(this.selection.count == 0) @@ -240,23 +279,37 @@ Scholar.CollectionTreeView.prototype.deleteSelection = function() this.selection.select(this.rowCount-1); } -Scholar.CollectionTreeView.prototype._showItem = function(item, level, beforeRow) +/* + * Called by various view functions to show a row + * + * itemGroup: reference to the ItemGroup + * level: the indent level of the row + * beforeRow: row index to insert new row before + */ +Scholar.CollectionTreeView.prototype._showItem = function(itemGroup, level, beforeRow) { - this._dataItems.splice(beforeRow, 0, [item, false, level]); this.rowCount++; + this._dataItems.splice(beforeRow, 0, [itemGroup, false, level]); this.rowCount++; } +/* + * Called by view to hide specified row + */ Scholar.CollectionTreeView.prototype._hideItem = function(row) { this._dataItems.splice(row,1); this.rowCount--; } +/* + * Returns a reference to the collection at row (see Scholar.Collection in data_access.js) + */ Scholar.CollectionTreeView.prototype._getItemAtRow = function(row) { return this._dataItems[row][0]; } /* - * Create hash map of collection ids to row indexes + * Creates hash map of collection ids to row indexes + * e.g., var rowForID = this._collectionRowMap[] */ Scholar.CollectionTreeView.prototype._refreshHashMap = function() { @@ -268,8 +321,17 @@ Scholar.CollectionTreeView.prototype._refreshHashMap = function() } -/* DRAG AND DROP FUNCTIONS */ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Drag-and-drop functions: +/// canDrop() and drop() are for nsITreeView +/// onDragStart(), getSupportedFlavours(), and onDrop() for nsDragAndDrop.js + nsTransferable.js +/// +//////////////////////////////////////////////////////////////////////////////// +/* + * Called while a drag is over the tree. + */ Scholar.CollectionTreeView.prototype.canDrop = function(row, orient) { if(typeof row == 'object') //workaround... two different services call canDrop (nsDragAndDrop, and the tree) @@ -288,23 +350,28 @@ Scholar.CollectionTreeView.prototype.canDrop = function(row, orient) } var data = dataSet.first.first; var dataType = data.flavour.contentType; - var rowCollection = this._getItemAtRow(row).ref; - //Check to make sure that the highlighting is done right - if(orient == 1 && row == 0 && dataType == 'scholar/collection') + + //Highlight the rows correctly on drag: + if(orient == 1 && row == 0 && dataType == 'scholar/collection') //for dropping collections into root level { return true; } - else if(orient == 0) + else if(orient == 0) //directly on a row... { + var rowCollection = this._getItemAtRow(row).ref; //the collection we are dragging over + if(dataType == 'scholar/item' || dataType == "text/x-moz-url") - return true; + return true; //items can be dropped on anything else if(dataType='scholar/collection' && data.data != rowCollection.getID() && !Scholar.Collections.get(data.data).hasDescendent('collection',rowCollection.getID()) ) - return true; + return true; //collections cannot be dropped on themselves, nor in their children } return false; } +/* + * Called when something's been dropped on or next to a row + */ Scholar.CollectionTreeView.prototype.drop = function(row, orient) { var dataSet = nsTransferable.get(this.getSupportedFlavours(),nsDragAndDrop.getDragData, true); @@ -340,19 +407,31 @@ Scholar.CollectionTreeView.prototype.drop = function(row, orient) } else if(dataType == 'text/x-moz-url' && this.canDrop(row, orient)) { - alert(data.data); - var targetCollection = this._getItemAtRow(row).ref; - /*for(var i = 0; i 0) @@ -92,6 +94,19 @@ ScholarItemPane = new function() { addCreatorRow('', '', 1); } + + //NOTES: + _notesMenu.removeAllItems(); + + var notes = _itemBeingEdited.getNotes(); + if(notes.length) + for(var i = 0; i < notes.length; i++) + _notesMenu.appendItem(_noteToTitle(_itemBeingEdited.getNote(notes[i])),notes[i]); + else + addNote(); + + _updateNoteCount(); + _notesMenu.selectedIndex = 0; } function addDynamicRow(label, value, beforeElement) @@ -248,6 +263,80 @@ ScholarItemPane = new function() _itemBeingEdited.setCreator(index, firstName, lastName, typeID); _itemBeingEdited.save(); } + + function modifySelectedNote() + { + if(_notesMenu.selectedIndex == -1) + return; + + var id = _notesMenu.selectedItem.value; + if(id) + { + _itemBeingEdited.updateNote(id,_notesField.value); + } + else //new note + { + id = _itemBeingEdited.addNote(_notesField.value); + _notesMenu.selectedItem.value = id; + } + var label = _notesField.value; + + _notesMenu.selectedItem.label = _noteToTitle(_notesField.value); + } + + function removeSelectedNote() + { + var id = _notesMenu.selectedItem.value; + if(id) + { + _itemBeingEdited.removeNote(id); + } + _notesMenu.removeitemAt(_notesMenu.selectedIndex); + + if(_notesMenu.firstChild.childNodes.length == 0) + addNote(); + + _updateNoteCount(); + } + + function addNote() + { + modifySelectedNote(); + _notesMenu.appendItem('Untitled Note'); + _notesMenu.selectedIndex = _notesMenu.firstChild.childNodes.length-1; + + _updateNoteCount(); + } + + function onNoteSelected() + { + var id = _notesMenu.selectedItem.value; + if(id) + _notesField.value = _itemBeingEdited.getNote(id); + else + _notesField.value = ""; + } + + function _noteToTitle(text) + { + var t = text.substring(0, Math.min(text.indexOf("\n"), 30) ); + + if(t == "") + { + return "Untitled Note"; + } + else + { + return t; + } + } + + function _updateNoteCount() + { + var c = _notesMenu.firstChild.childNodes.length; + + _notesLabel.value = c + " note" + (c != 1 ? "s" : "") + ":"; + } } addEventListener("load", function(e) { ScholarItemPane.onLoad(e); }, false); diff --git a/chrome/chromeFiles/content/scholar/itemPane.xul b/chrome/chromeFiles/content/scholar/itemPane.xul index abee881de..1e3251cda 100644 --- a/chrome/chromeFiles/content/scholar/itemPane.xul +++ b/chrome/chromeFiles/content/scholar/itemPane.xul @@ -12,8 +12,16 @@ - + diff --git a/chrome/chromeFiles/content/scholar/itemTreeView.js b/chrome/chromeFiles/content/scholar/itemTreeView.js index 7648879a8..c6e11269f 100644 --- a/chrome/chromeFiles/content/scholar/itemTreeView.js +++ b/chrome/chromeFiles/content/scholar/itemTreeView.js @@ -1,3 +1,14 @@ +//////////////////////////////////////////////////////////////////////////////// +/// +/// ItemTreeView +/// -- handles the link between an individual tree and the data layer +/// -- displays only items (no collections, no hierarchy) +/// +//////////////////////////////////////////////////////////////////////////////// + +/* + * Constructor the the ItemTreeView object + */ Scholar.ItemTreeView = function(itemGroup) { this._itemGroup = itemGroup; @@ -9,6 +20,9 @@ Scholar.ItemTreeView = function(itemGroup) this._unregisterID = Scholar.Notifier.registerItemTree(this); } +/* + * Called by the tree itself + */ Scholar.ItemTreeView.prototype.setTree = function(treebox) { if(this._treebox) @@ -25,6 +39,10 @@ Scholar.ItemTreeView.prototype.setTree = function(treebox) } } +/* + * Reload the rows from the data access methods + * (doesn't call the tree.invalidate methods, etc.) + */ Scholar.ItemTreeView.prototype.refresh = function() { this._dataItems = new Array(); @@ -38,6 +56,9 @@ Scholar.ItemTreeView.prototype.refresh = function() this._refreshHashMap(); } +/* + * Called by Scholar.Notifier on any changes to items in the data layer + */ Scholar.ItemTreeView.prototype.notify = function(action, type, ids) { var madeChanges = false; @@ -112,11 +133,21 @@ Scholar.ItemTreeView.prototype.notify = function(action, type, ids) this.selection.selectEventsSuppressed = false; } +/* + * Unregisters view from Scholar.Notifier (called on window close) + */ Scholar.ItemTreeView.prototype.unregister = function() { Scholar.Notifier.unregisterItemTree(this._unregisterID); } +//////////////////////////////////////////////////////////////////////////////// +/// +/// nsITreeView functions +/// http://www.xulplanet.com/references/xpcomref/ifaces/nsITreeView.html +/// +//////////////////////////////////////////////////////////////////////////////// + Scholar.ItemTreeView.prototype.getCellText = function(row, column) { var obj = this._getItemAtRow(row); @@ -175,9 +206,12 @@ Scholar.ItemTreeView.prototype.cycleHeader = function(column) this._treebox.invalidate(); } +/* + * Sort the items by the currently sorted column. + * Simply uses Array.sort() function, and refreshes the hash map. + */ Scholar.ItemTreeView.prototype.sort = function() { - var column = this._treebox.columns.getSortedColumn() var order = column.element.getAttribute('sortDirection') == 'descending'; @@ -199,13 +233,13 @@ Scholar.ItemTreeView.prototype.sort = function() } } - function oppSort(a,b) + function oppositeSort(a,b) { return(columnSort(a,b) * -1); } if(order) - this._dataItems.sort(oppSort); + this._dataItems.sort(oppositeSort); else this._dataItems.sort(columnSort); @@ -213,6 +247,15 @@ Scholar.ItemTreeView.prototype.sort = function() } +//////////////////////////////////////////////////////////////////////////////// +/// +/// Additional functions for managing data in the tree +/// +//////////////////////////////////////////////////////////////////////////////// + +/* + * Delete the selection + */ Scholar.ItemTreeView.prototype.deleteSelection = function() { if(this.selection.count == 0) @@ -246,6 +289,9 @@ Scholar.ItemTreeView.prototype.deleteSelection = function() this._treebox.endUpdateBatch(); } +/* + * Set the search filter on the view + */ Scholar.ItemTreeView.prototype.searchText = function(search) { this.selection.selectEventsSuppressed = true; @@ -263,23 +309,35 @@ Scholar.ItemTreeView.prototype.searchText = function(search) this._treebox.invalidate(); } +/* + * Called by various view functions to show a row + * + * item: reference to the Item + * beforeRow: row index to insert new row before + */ Scholar.ItemTreeView.prototype._showItem = function(item, beforeRow) { this._dataItems.splice(beforeRow, 0, item); this.rowCount++; } +/* + * Called by view to hide specified row + */ Scholar.ItemTreeView.prototype._hideItem = function(row) { this._dataItems.splice(row,1); this.rowCount--; } +/* + * Returns a reference to the item at row (see Scholar.Item in data_access.js) + */ Scholar.ItemTreeView.prototype._getItemAtRow = function(row) { return this._dataItems[row]; } /* - * Create hash map of item ids to row indexes + * Create hash map of item ids to row indexes */ Scholar.ItemTreeView.prototype._refreshHashMap = function() { @@ -288,6 +346,9 @@ Scholar.ItemTreeView.prototype._refreshHashMap = function() this._itemRowMap[this._getItemAtRow(i).getID()] = i; } +/* + * Saves the ids of currently selected items for later + */ Scholar.ItemTreeView.prototype.saveSelection = function() { this._savedSelection = new Array(); @@ -302,6 +363,9 @@ Scholar.ItemTreeView.prototype.saveSelection = function() } } +/* + * Sets the selection based on saved selection ids (see above) + */ Scholar.ItemTreeView.prototype.rememberSelection = function() { this.selection.clearSelection(); @@ -312,15 +376,26 @@ Scholar.ItemTreeView.prototype.rememberSelection = function() } } -/* DRAG AND DROP FUNCTIONS */ +//////////////////////////////////////////////////////////////////////////////// +/// +/// Drag-and-drop functions: +/// for nsDragAndDrop.js + nsTransferable.js +/// +//////////////////////////////////////////////////////////////////////////////// +/* + * Begin a drag + */ Scholar.ItemTreeView.prototype.onDragStart = function (evt,transferData,action) { transferData.data=new TransferData(); this.saveSelection(); transferData.data.addDataForFlavour("scholar/item",this._savedSelection); } - + +/* + * Called by nsDragAndDrop.js for any sort of drop on the tree + */ Scholar.ItemTreeView.prototype.getSupportedFlavours = function () { var flavors = new FlavourSet(); @@ -329,28 +404,39 @@ Scholar.ItemTreeView.prototype.getSupportedFlavours = function () return flavors; } +/* + * Called by nsDragAndDrop.js for any sort of drop on the tree + */ Scholar.ItemTreeView.prototype.onDrop = function (evt,data,session) { var dataType = data.flavour.contentType; - var ids = data.data.split(','); if(dataType == 'scholar/item') { + var ids = data.data.split(','); for(var i = 0; i