commit 8ec248f7ecc701c015a51f83c502518a142f76f3
parent d22f762bb69d9738c46a786d5de84aa52afd8311
Author: Dan Stillman <dstillman@zotero.org>
Date: Mon, 4 May 2015 02:35:52 -0400
Remove some unnecessary asyncness in tree views
E.g., closing a container doesn't need to yield
Diffstat:
2 files changed, 131 insertions(+), 105 deletions(-)
diff --git a/chrome/content/zotero/xpcom/collectionTreeView.js b/chrome/content/zotero/xpcom/collectionTreeView.js
@@ -639,39 +639,47 @@ Zotero.CollectionTreeView.prototype.hasNextSibling = function(row, afterIndex)
/*
* Opens/closes the specified row
*/
-Zotero.CollectionTreeView.prototype.toggleOpenState = Zotero.Promise.coroutine(function* (row)
-{
- var count = 0;
- var thisLevel = this.getLevel(row);
-
- //this._treebox.beginUpdateBatch();
+Zotero.CollectionTreeView.prototype.toggleOpenState = Zotero.Promise.coroutine(function* (row) {
if (this.isContainerOpen(row)) {
- while((row + 1 < this._rows.length) && (this.getLevel(row + 1) > thisLevel))
- {
- this._removeRow(row+1);
- count--;
- }
- // Remove from the end of the row's children
- this._treebox.rowCountChanged(row + 1 + Math.abs(count), count);
+ return this._closeContainer(row);
}
- else {
- var treeRow = this.getRow(row);
- if (treeRow.isLibrary(true) || treeRow.isCollection()) {
- count = yield this._expandRow(this._rows, row, true);
- }
- this.rowCount += count;
- this._treebox.rowCountChanged(row + 1, count);
+
+ var count = 0;
+
+ var treeRow = this.getRow(row);
+ if (treeRow.isLibrary(true) || treeRow.isCollection()) {
+ count = yield this._expandRow(this._rows, row, true);
}
+ this.rowCount += count;
+ this._treebox.rowCountChanged(row + 1, count);
// Toggle container open value
- this._rows[row][1] = !this._rows[row][1];
+ this._rows[row][1] = true;
this._treebox.invalidateRow(row);
- //this._treebox.endUpdateBatch();
this._refreshRowMap();
- yield this._rememberOpenStates();
});
+Zotero.CollectionTreeView.prototype._closeContainer = function (row) {
+ if (!this.isContainerOpen(row)) return;
+
+ var count = 0;
+ var level = this.getLevel(row);
+
+ // Remove child rows
+ while ((row + 1 < this._rows.length) && (this.getLevel(row + 1) > level)) {
+ this._removeRow(row + 1);
+ count--;
+ }
+ // Mark as removed from the end of the row's children
+ this._treebox.rowCountChanged(row + 1 + Math.abs(count), count);
+
+ this._rows[row][1] = false;
+ this._treebox.invalidateRow(row);
+ this._refreshRowMap();
+}
+
+
Zotero.CollectionTreeView.prototype.isSelectable = function (row, col) {
var treeRow = this.getRow(row);
switch (treeRow.type) {
@@ -744,7 +752,7 @@ Zotero.CollectionTreeView.prototype.expandLibrary = Zotero.Promise.coroutine(fun
});
-Zotero.CollectionTreeView.prototype.collapseLibrary = Zotero.Promise.coroutine(function* () {
+Zotero.CollectionTreeView.prototype.collapseLibrary = function () {
var selectedLibraryID = this.getSelectedLibraryID();
if (selectedLibraryID === false) {
return;
@@ -764,8 +772,8 @@ Zotero.CollectionTreeView.prototype.collapseLibrary = Zotero.Promise.coroutine(f
found = true;
- if (this.isContainer(i) && this.isContainerOpen(i)) {
- yield this.toggleOpenState(i);
+ if (this.isContainer(i)) {
+ this._closeContainer(i);
}
}
@@ -773,7 +781,7 @@ Zotero.CollectionTreeView.prototype.collapseLibrary = Zotero.Promise.coroutine(f
// Select the collapsed library
this.selectLibrary(selectedLibraryID);
-});
+};
Zotero.CollectionTreeView.prototype.expandToCollection = Zotero.Promise.coroutine(function* (collectionID) {
@@ -870,7 +878,7 @@ Zotero.CollectionTreeView.prototype.selectCollection = Zotero.Promise.coroutine(
});
-Zotero.CollectionTreeView.prototype.selectTrash = function (libraryID) {
+Zotero.CollectionTreeView.prototype.selectTrash = Zotero.Promise.coroutine(function* (libraryID) {
if (Zotero.suppressUIUpdates) {
Zotero.debug("UI updates suppressed -- not changing library selection");
return false;
@@ -887,7 +895,7 @@ Zotero.CollectionTreeView.prototype.selectTrash = function (libraryID) {
// If in My Library and it's collapsed, open it
if (!libraryID && !this.isContainerOpen(0)) {
- this.toggleOpenState(0);
+ yield this.toggleOpenState(0);
}
// Find library trash
@@ -897,13 +905,13 @@ Zotero.CollectionTreeView.prototype.selectTrash = function (libraryID) {
// If group header is closed, open it
if (itemGroup.isHeader() && itemGroup.ref.id == 'group-libraries-header'
&& !this.isContainerOpen(i)) {
- this.toggleOpenState(i);
+ yield this.toggleOpenState(i);
continue;
}
if (itemGroup.isLibrary(true) && itemGroup.ref.libraryID == libraryID
&& !this.isContainerOpen(i)) {
- this.toggleOpenState(i);
+ yield this.toggleOpenState(i);
continue;
}
@@ -915,7 +923,7 @@ Zotero.CollectionTreeView.prototype.selectTrash = function (libraryID) {
}
return false;
-}
+});
/**
@@ -1001,8 +1009,8 @@ Zotero.CollectionTreeView.prototype.deleteSelection = Zotero.Promise.coroutine(f
//collapse open collections
for (let i=0; i<this.rowCount; i++) {
- if (this.selection.isSelected(i) && this.isContainer(i) && this.isContainerOpen(i)) {
- yield this.toggleOpenState(i);
+ if (this.selection.isSelected(i) && this.isContainer(i)) {
+ this._closeContainer(i);
}
}
this._refreshRowMap();
diff --git a/chrome/content/zotero/xpcom/itemTreeView.js b/chrome/content/zotero/xpcom/itemTreeView.js
@@ -92,7 +92,6 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
if (this._ownerDocument.defaultView.ZoteroPane_Local) {
this._ownerDocument.defaultView.ZoteroPane_Local.setItemsPaneMessage(Zotero.getString('pane.items.loading'));
- this._waitAfter = start + 100;
}
if (Zotero.locked) {
@@ -237,9 +236,6 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
yield this.sort();
- // Only yield if there are callbacks; otherwise, we're almost done
- if (this._listeners.load.length && this._waitAfter && Date.now() > this._waitAfter) yield Zotero.Promise.resolve();
-
yield this.expandMatchParents();
@@ -254,7 +250,6 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
this.collectionTreeRow.itemToSelect = null;
}
- delete this._waitAfter;
Zotero.debug("Set tree in "+(Date.now()-start)+" ms");
this._initialized = true;
@@ -323,7 +318,7 @@ Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(f
//this._treebox.beginUpdateBatch();
}
var savedSelection = this.getSelectedItems(true);
- var savedOpenState = yield this.saveOpenState();
+ var savedOpenState = this._saveOpenState();
var oldCount = this.rowCount;
var newSearchItemIDs = {};
@@ -372,8 +367,6 @@ Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(f
}
}
- if(this._waitAfter && Date.now() > this._waitAfter) yield Zotero.Promise.resolve();
-
this._rows = newRows;
this.rowCount = this._rows.length;
var diff = this.rowCount - oldCount;
@@ -1194,58 +1187,53 @@ Zotero.ItemTreeView.prototype.toggleOpenState = Zotero.Promise.coroutine(functio
return;
}
- var count = 0;
- var thisLevel = this.getLevel(row);
-
- // Close
if (this.isContainerOpen(row)) {
- while((row + 1 < this._rows.length) && (this.getLevel(row + 1) > thisLevel))
- {
- this._removeRow(row+1);
- count--;
- }
- // Remove from the end of the row's children
- this._treebox.rowCountChanged(row + 1 + Math.abs(count), count);
+ return this._closeContainer(row, skipItemMapRefresh);
}
+
+ var count = 0;
+ var level = this.getLevel(row);
+
+ //
// Open
- else {
- var item = this.getRow(row).ref;
- yield item.loadChildItems();
-
- //Get children
- var includeTrashed = this.collectionTreeRow.isTrash();
- var attachments = item.getAttachments(includeTrashed);
- var notes = item.getNotes(includeTrashed);
-
- var newRows;
- if(attachments && notes)
- newRows = notes.concat(attachments);
- else if(attachments)
- newRows = attachments;
- else if(notes)
- newRows = notes;
-
- if (newRows) {
- newRows = yield Zotero.Items.getAsync(newRows);
-
- for(var i = 0; i < newRows.length; i++)
- {
- count++;
- this._addRow(
- this._rows,
- new Zotero.ItemTreeRow(newRows[i], thisLevel + 1, false),
- row + i + 1
- );
- }
- this.rowCount += count;
- this._treebox.rowCountChanged(row + 1, count);
+ //
+ var item = this.getRow(row).ref;
+ yield item.loadChildItems();
+
+ //Get children
+ var includeTrashed = this.collectionTreeRow.isTrash();
+ var attachments = item.getAttachments(includeTrashed);
+ var notes = item.getNotes(includeTrashed);
+
+ var newRows;
+ if (attachments.length && notes.length) {
+ newRows = notes.concat(attachments);
+ }
+ else if (attachments.length) {
+ newRows = attachments;
+ }
+ else if (notes.length) {
+ newRows = notes;
+ }
+
+ if (newRows) {
+ newRows = yield Zotero.Items.getAsync(newRows);
+
+ for (let i = 0; i < newRows.length; i++) {
+ count++;
+ this._addRow(
+ this._rows,
+ new Zotero.ItemTreeRow(newRows[i], level + 1, false),
+ row + i + 1
+ );
}
+ this.rowCount += count;
+ this._treebox.rowCountChanged(row + 1, count);
}
- // Toggle container open value
- this._rows[row].isOpen = !this._rows[row].isOpen;
+ this._rows[row].isOpen = true;
- if (!count) {
+ if (count == 0) {
return;
}
@@ -1258,6 +1246,39 @@ Zotero.ItemTreeView.prototype.toggleOpenState = Zotero.Promise.coroutine(functio
});
+Zotero.ItemTreeView.prototype._closeContainer = function (row, skipItemMapRefresh) {
+ // isContainer == false shouldn't happen but does if an item is dragged over a closed
+ // container until it opens and then released, since the container is no longer in the same
+ // place when the spring-load closes
+ if (!this.isContainer(row)) return;
+ if (!this.isContainerOpen(row)) return;
+
+ var count = 0;
+ var level = this.getLevel(row);
+
+ // Remove child rows
+ while ((row + 1 < this._rows.length) && (this.getLevel(row + 1) > level)) {
+ this._removeRow(row+1);
+ count--;
+ }
+ // Mark as removed from the end of the row's children
+ this._treebox.rowCountChanged(row + 1 + Math.abs(count), count);
+
+ this._rows[row].isOpen = false;
+
+ if (count == 0) {
+ return;
+ }
+
+ this._treebox.invalidateRow(row);
+
+ if (!skipItemMapRefresh) {
+ Zotero.debug('Refreshing hash map');
+ this._refreshItemRowMap();
+ }
+}
+
+
Zotero.ItemTreeView.prototype.isSorted = function()
{
// We sort by the first column if none selected, so return true
@@ -1320,11 +1341,11 @@ Zotero.ItemTreeView.prototype.sort = Zotero.Promise.coroutine(function* (itemID)
}
this._needsSort = false;
- // Single child item sort -- just toggle parent open and closed
+ // Single child item sort -- just toggle parent closed and open
if (itemID && this._itemRowMap[itemID] &&
this.getRow(this._itemRowMap[itemID]).ref.parentKey) {
let parentIndex = this.getParentIndex(this._itemRowMap[itemID]);
- yield this.toggleOpenState(parentIndex);
+ this._closeContainer(parentIndex);
yield this.toggleOpenState(parentIndex);
return;
}
@@ -1527,7 +1548,7 @@ Zotero.ItemTreeView.prototype.sort = Zotero.Promise.coroutine(function* (itemID)
//this._treebox.beginUpdateBatch();
}
var savedSelection = this.getSelectedItems(true);
- var openItemIDs = yield this.saveOpenState(true);
+ var openItemIDs = this._saveOpenState(true);
// Single-row sort
if (itemID) {
@@ -1646,9 +1667,8 @@ Zotero.ItemTreeView.prototype.selectItem = Zotero.Promise.coroutine(function* (i
// If parent is already open and we haven't found the item, the child
// hasn't yet been added to the view, so close parent to allow refresh
- if (this.isContainerOpen(parentRow)) {
- yield this.toggleOpenState(parentRow);
- }
+ this._closeContainer(parentRow);
+
// Open the parent
yield this.toggleOpenState(parentRow);
row = this._itemRowMap[id];
@@ -1792,8 +1812,8 @@ Zotero.ItemTreeView.prototype.deleteSelection = Zotero.Promise.coroutine(functio
// Collapse open items
for (var i=0; i<this.rowCount; i++) {
- if (this.selection.isSelected(i) && this.isContainer(i) && this.isContainerOpen(i)) {
- yield this.toggleOpenState(i, true);
+ if (this.selection.isSelected(i) && this.isContainer(i)) {
+ this._closeContainer(i, true);
}
}
this._refreshItemRowMap();
@@ -1948,9 +1968,7 @@ Zotero.ItemTreeView.prototype.rememberSelection = Zotero.Promise.coroutine(funct
}
if (this._itemRowMap[parent] != null) {
- if (this.isContainerOpen(this._itemRowMap[parent])) {
- yield this.toggleOpenState(this._itemRowMap[parent]);
- }
+ this._closeContainer(this._itemRowMap[parent]);
yield this.toggleOpenState(this._itemRowMap[parent]);
this.selection.toggleSelect(this._itemRowMap[selection[i]]);
}
@@ -1977,7 +1995,7 @@ Zotero.ItemTreeView.prototype.selectSearchMatches = Zotero.Promise.coroutine(fun
});
-Zotero.ItemTreeView.prototype.saveOpenState = Zotero.Promise.coroutine(function* (close) {
+Zotero.ItemTreeView.prototype._saveOpenState = function (close) {
var itemIDs = [];
if (close) {
if (!this.selection.selectEventsSuppressed) {
@@ -1989,7 +2007,7 @@ Zotero.ItemTreeView.prototype.saveOpenState = Zotero.Promise.coroutine(function*
if (this.isContainer(i) && this.isContainerOpen(i)) {
itemIDs.push(this.getRow(i).ref.id);
if (close) {
- yield this.toggleOpenState(i, true);
+ this._closeContainer(i, true);
}
}
}
@@ -2001,7 +2019,7 @@ Zotero.ItemTreeView.prototype.saveOpenState = Zotero.Promise.coroutine(function*
}
}
return itemIDs;
-});
+}
Zotero.ItemTreeView.prototype.rememberOpenState = Zotero.Promise.coroutine(function* (itemIDs) {
@@ -2097,8 +2115,8 @@ Zotero.ItemTreeView.prototype.collapseAllRows = Zotero.Promise.coroutine(functio
var unsuppress = this.selection.selectEventsSuppressed = true;
//this._treebox.beginUpdateBatch();
for (var i=0; i<this.rowCount; i++) {
- if (this.isContainer(i) && this.isContainerOpen(i)) {
- yield this.toggleOpenState(i, true);
+ if (this.isContainer(i)) {
+ this._closeContainer(i, true);
}
}
this._refreshItemRowMap();
@@ -2132,8 +2150,8 @@ Zotero.ItemTreeView.prototype.collapseSelectedRows = Zotero.Promise.coroutine(fu
for (var i = 0, len = this.selection.getRangeCount(); i<len; i++) {
this.selection.getRangeAt(i, start, end);
for (var j = start.value; j <= end.value; j++) {
- if (this.isContainer(j) && this.isContainerOpen(j)) {
- yield this.toggleOpenState(j, true);
+ if (this.isContainer(j)) {
+ this._closeContainer(j, true);
}
}
}