//////////////////////////////////////////////////////////////////////////////// /// /// 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; this._treebox = null; this._savedSelection = null; this.refresh(); this._unregisterID = Scholar.Notifier.registerItemTree(this); } /* * Called by the tree itself */ Scholar.ItemTreeView.prototype.setTree = function(treebox) { if(this._treebox) return; this._treebox = treebox; if(!this.isSorted()) { this.cycleHeader(this._treebox.columns.getNamedColumn('firstCreator')); } else { this.sort(); } } /* * 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(); this.rowCount = 0; var newRows = this._itemGroup.getChildItems(); for(var i = 0; i < newRows.length; i++) if(newRows[i]) this._showItem(new Scholar.ItemTreeView.TreeRow(newRows[i],0,false), i+1); //item ref, before row 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; this.selection.selectEventsSuppressed = true; this.saveSelection(); if((action == 'remove' && !this._itemGroup.isLibrary()) || (action == 'delete' && this._itemGroup.isLibrary())) { ids = Scholar.flattenArguments(ids); //Since a remove involves shifting of rows, we have to do it in order //sort the ids by row var rows = new Array(); for(var i=0, len=ids.length; i 0) { rows.sort(function(a,b) { return a-b }); for(var i=0, len=rows.length; i= 0; i--) if(this.getLevel(i) < thisLevel) return i; return -1; } Scholar.ItemTreeView.prototype.hasNextSibling = function(row,afterIndex) { var thisLevel = this.getLevel(row); for(var i = afterIndex + 1; i < this.rowCount; i++) { var nextLevel = this.getLevel(i); if(nextLevel == thisLevel) return true; else if(nextLevel < thisLevel) return false; } } Scholar.ItemTreeView.prototype.toggleOpenState = function(row) { var count = 0; //used to tell the tree how many rows were added/removed var thisLevel = this.getLevel(row); if(this.isContainerOpen(row)) { while((row + 1 < this._dataItems.length) && (this.getLevel(row + 1) > thisLevel)) { this._hideItem(row+1); count--; //count is negative when closing a container because we are removing rows } } else { var item = this._getItemAtRow(row).ref; //Get children var files = item.getFiles(); var notes = item.getNotes(); var newRows; if(files && notes) newRows = files.concat(notes); else if(files) newRows = files; else if(notes) newRows = notes; newRows = Scholar.Items.get(newRows); for(var i = 0; i < newRows.length; i++) { count++; this._showItem(new Scholar.ItemTreeView.TreeRow(newRows[i],thisLevel+1,false), row+i+1); //item ref, before row } } this._treebox.beginUpdateBatch(); this._dataItems[row].isOpen = !this._dataItems[row].isOpen; this._treebox.rowCountChanged(row+1, count); //tell treebox to repaint these this._treebox.invalidateRow(row); this._treebox.endUpdateBatch(); this._refreshHashMap(); } Scholar.ItemTreeView.prototype.isSorted = function() { for(var i=0, len=this._treebox.columns.count; i typeB) ? -1 : (typeA < typeB) ? 1 : 0; } } else if(column.id == 'numNotes') { function columnSort(a,b) { return b.numNotes() - a.numNotes(); } } else { function columnSort(a,b) { var fieldA = a.getField(column.id); var fieldB = b.getField(column.id); if(typeof fieldA == 'string') { fieldA = fieldA.toLowerCase(); fieldB = fieldB.toLowerCase(); } return (fieldA > fieldB) ? -1 : (fieldA < fieldB) ? 1 : 0; } } function doSort(a,b) { var s = columnSort(a,b); if(s) return s; else return secondarySort(a,b); } function oppositeSort(a,b) { return(doSort(a,b) * -1); } function secondarySort(a,b) { return (a.getField('dateModified') > b.getField('dateModified')) ? -1 : (a.getField('dateModified') < b.getField('dateModified')) ? 1 : 0; } var openRows = new Array(); for(var i = 0; i < this._dataItems.length; i++) { if(this.isContainer(i) && this.isContainerOpen(i)) { openRows.push(this._getItemAtRow(i).ref.getID()); this.toggleOpenState(i); } } if(order) this._dataItems.sort(oppositeSort); else this._dataItems.sort(doSort); this._refreshHashMap(); for(var i = 0; i < openRows.length; i++) this.toggleOpenState(this._itemRowMap[openRows[i]]); } //////////////////////////////////////////////////////////////////////////////// /// /// Additional functions for managing data in the tree /// //////////////////////////////////////////////////////////////////////////////// /* * Delete the selection */ Scholar.ItemTreeView.prototype.deleteSelection = function() { if(this.selection.count == 0) return; //collapse open items for(var i=0; i 0)); } Scholar.ItemTreeCommandController.prototype.doCommand = function(cmd) { if(cmd == 'cmd_selectAll') this.tree.view.selection.selectAll(); else if(cmd == 'cmd_delete') ScholarPane.deleteSelectedItem(); } Scholar.ItemTreeCommandController.prototype.onEvent = function(evt) { } //////////////////////////////////////////////////////////////////////////////// /// /// 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(); flavors.appendFlavour("scholar/item"); flavors.appendFlavour("text/x-moz-url"); 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; if(dataType == 'scholar/item') { var ids = data.data.split(','); for(var i = 0; i -1) t = t.substring(0,n); return t; } } else { return this.ref.getField(field); } } Scholar.ItemTreeView.TreeRow.prototype.getType = function() { return this.ref.getType(); } Scholar.ItemTreeView.TreeRow.prototype.numNotes = function() { if(this.isRegularItem()) return this.ref.numNotes(); else return 0; } Scholar.ItemTreeView.TreeRow.prototype.numFiles = function() { if(this.isRegularItem()) return this.ref.numFiles(); else return 0; }