summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorvsevik@chromium.org <vsevik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 13:48:10 +0000
committervsevik@chromium.org <vsevik@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-26 13:48:10 +0000
commitd3fe3b27838f4ec1787bec09437a075afcf0a131 (patch)
tree962de966ea6036430b4008f20864e789cb2069ed /chrome
parentf117eb9ad41c134ff895f58d20f05bacab76344a (diff)
downloadchromium_src-d3fe3b27838f4ec1787bec09437a075afcf0a131.zip
chromium_src-d3fe3b27838f4ec1787bec09437a075afcf0a131.tar.gz
chromium_src-d3fe3b27838f4ec1787bec09437a075afcf0a131.tar.bz2
Move sorting logic from table to list.
BUG=82868 Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=86065 Review URL: http://codereview.chromium.org/7038024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86814 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/resources/file_manager/js/file_manager.js24
-rw-r--r--chrome/browser/resources/file_manager/main.html3
-rw-r--r--chrome/browser/resources/options/autofill_options_list.js3
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/array_data_model.js239
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/list.js90
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/list_selection_model.js48
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js36
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/table.js63
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/table/table_data_model.js275
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/table/table_selection_model.js65
-rw-r--r--chrome/browser/resources/shared/js/cr/ui/table/table_single_selection_model.js59
-rw-r--r--chrome/browser/resources/shared_resources.grd6
12 files changed, 329 insertions, 582 deletions
diff --git a/chrome/browser/resources/file_manager/js/file_manager.js b/chrome/browser/resources/file_manager/js/file_manager.js
index 6ef815f..09d0dab 100644
--- a/chrome/browser/resources/file_manager/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/js/file_manager.js
@@ -518,20 +518,18 @@ FileManager.prototype = {
// Always sharing the data model between the detail/thumb views confuses
// them. Instead we maintain this bogus data model, and hook it up to the
// view that is not in use.
- this.emptyDataModel_ = new cr.ui.table.TableDataModel([]);
+ this.emptyDataModel_ = new cr.ui.ArrayDataModel([]);
- this.dataModel_ = new cr.ui.table.TableDataModel([]);
+ this.dataModel_ = new cr.ui.ArrayDataModel([]);
this.dataModel_.sort('name');
- this.dataModel_.addEventListener('sorted',
- this.onDataModelSorted_.bind(this));
this.dataModel_.prepareSort = this.prepareSort_.bind(this);
if (this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FILE ||
this.dialogType_ == FileManager.DialogType.SELECT_OPEN_FOLDER ||
this.dialogType_ == FileManager.DialogType.SELECT_SAVEAS_FILE) {
- this.selectionModelClass_ = cr.ui.table.TableSingleSelectionModel;
+ this.selectionModelClass_ = cr.ui.ListSingleSelectionModel;
} else {
- this.selectionModelClass_ = cr.ui.table.TableSelectionModel;
+ this.selectionModelClass_ = cr.ui.ListSelectionModel;
}
this.initTable_();
@@ -1426,16 +1424,6 @@ FileManager.prototype = {
};
/**
- * Invoked by the table dataModel after a sort completes.
- *
- * We use this hook to make sure selected files stay visible after a sort.
- */
- FileManager.prototype.onDataModelSorted_ = function() {
- var i = this.currentList_.selectionModel.leadIndex;
- this.currentList_.scrollIntoView(i);
- }
-
- /**
* Update the selection summary UI when the selection summarization completes.
*/
FileManager.prototype.onSelectionSummarized_ = function() {
@@ -1576,9 +1564,6 @@ FileManager.prototype = {
function onReadSome(entries) {
if (entries.length == 0) {
- if (self.dataModel_.sortStatus.field != 'name')
- self.dataModel_.updateIndex(0);
-
if (opt_callback)
opt_callback();
return;
@@ -1624,7 +1609,6 @@ FileManager.prototype = {
var spliceArgs = [].slice.call(this.rootEntries_);
spliceArgs.unshift(0, 0); // index, deleteCount
self.dataModel_.splice.apply(self.dataModel_, spliceArgs);
- self.dataModel_.updateIndex(0);
if (opt_callback)
opt_callback();
diff --git a/chrome/browser/resources/file_manager/main.html b/chrome/browser/resources/file_manager/main.html
index 53013f3..8fdcae5 100644
--- a/chrome/browser/resources/file_manager/main.html
+++ b/chrome/browser/resources/file_manager/main.html
@@ -30,9 +30,6 @@
'cr/ui/splitter.js',
'cr/ui/table/table_splitter.js',
- 'cr/ui/table/table_selection_model.js',
- 'cr/ui/table/table_single_selection_model.js',
- 'cr/ui/table/table_data_model.js',
'cr/ui/table/table_column.js',
'cr/ui/table/table_column_model.js',
diff --git a/chrome/browser/resources/options/autofill_options_list.js b/chrome/browser/resources/options/autofill_options_list.js
index 3fadeab..86aaae8 100644
--- a/chrome/browser/resources/options/autofill_options_list.js
+++ b/chrome/browser/resources/options/autofill_options_list.js
@@ -174,6 +174,9 @@ cr.define('options.autofillOptions', function() {
if (this.input.value &&
this.list.dataModel.indexOf(this.input.value) == -1) {
+ // It is important that updateIndex is done before validateAndSave.
+ // Otherwise we can not be sure about AddRow index.
+ this.list.dataModel.updateIndex(i);
this.list.validateAndSave(i, 0, this.input.value);
} else {
this.input.value = '';
diff --git a/chrome/browser/resources/shared/js/cr/ui/array_data_model.js b/chrome/browser/resources/shared/js/cr/ui/array_data_model.js
index 64da3be..bc26eb6 100644
--- a/chrome/browser/resources/shared/js/cr/ui/array_data_model.js
+++ b/chrome/browser/resources/shared/js/cr/ui/array_data_model.js
@@ -11,13 +11,18 @@ cr.define('cr.ui', function() {
const Event = cr.Event;
/**
- * A data model that wraps a simple array.
+ * A data model that wraps a simple array and supports sorting by storing
+ * initial indexes of elements for each position in sorted array.
* @param {!Array} array The underlying array.
* @constructor
* @extends {EventTarget}
*/
function ArrayDataModel(array) {
this.array_ = array;
+ this.indexes_ = [];
+ for (var i = 0; i < array.length; i++) {
+ this.indexes_.push(i);
+ }
}
ArrayDataModel.prototype = {
@@ -33,11 +38,46 @@ cr.define('cr.ui', function() {
/**
* Returns the item at the given index.
+ * This implementation returns the item at the given index in the sorted
+ * array.
* @param {number} index The index of the element to get.
* @return {*} The element at the given index.
*/
item: function(index) {
- return this.array_[index];
+ if (index >= 0 && index < this.length)
+ return this.array_[this.indexes_[index]];
+ return undefined;
+ },
+
+ /**
+ * Returns compare function set for given field.
+ * @param {string} field The field to get compare function for.
+ * @return {function(*, *): number} Compare function set for given field.
+ */
+ compareFunction: function(field) {
+ return this.compareFunctions_[field];
+ },
+
+ /**
+ * Sets compare function for given field.
+ * @param {string} field The field to set compare function.
+ * @param {function(*, *): number} Compare function to set for given field.
+ */
+ setCompareFunction: function(field, compareFunction) {
+ this.compareFunctions_[field] = compareFunction;
+ },
+
+ /**
+ * Returns current sort status.
+ * @return {!Object} Current sort status.
+ */
+ get sortStatus() {
+ if (this.sortStatus_) {
+ return this.createSortStatus(
+ this.sortStatus_.field, this.sortStatus_.direction);
+ } else {
+ return this.createSortStatus(null, null);
+ }
},
/**
@@ -63,27 +103,60 @@ cr.define('cr.ui', function() {
/**
* This removes and adds items to the model.
- *
* This dispatches a splice event.
- *
+ * This implementation runs sort after splice and creates permutation for
+ * the whole change.
* @param {number} index The index of the item to update.
* @param {number} deleteCount The number of items to remove.
* @param {...*} The items to add.
* @return {!Array} An array with the removed items.
*/
splice: function(index, deleteCount, var_args) {
+ var addCount = arguments.length - 2;
+ var newIndexes = [];
+ var deletePermutation = [];
+ var deleted = 0;
+ for (var i = 0; i < this.indexes_.length; i++) {
+ var oldIndex = this.indexes_[i];
+ if (oldIndex < index) {
+ newIndexes.push(oldIndex);
+ deletePermutation.push(i - deleted);
+ } else if (oldIndex >= index + deleteCount) {
+ newIndexes.push(oldIndex - deleteCount + addCount);
+ deletePermutation.push(i - deleted);
+ } else {
+ deletePermutation.push(-1);
+ deleted++;
+ }
+ }
+ for (var i = 0; i < addCount; i++) {
+ newIndexes.push(index + i);
+ }
+ this.indexes_ = newIndexes;
+
var arr = this.array_;
// TODO(arv): Maybe unify splice and change events?
- var e = new Event('splice');
- e.index = index;
- e.removed = arr.slice(index, index + deleteCount);
- e.added = Array.prototype.slice.call(arguments, 2);
+ var spliceEvent = new Event('splice');
+ spliceEvent.index = index;
+ spliceEvent.removed = arr.slice(index, index + deleteCount);
+ spliceEvent.added = Array.prototype.slice.call(arguments, 2);
var rv = arr.splice.apply(arr, arguments);
- this.dispatchEvent(e);
+ // if sortStatus.field is null, this restores original order.
+ var sortPermutation = this.doSort_(this.sortStatus.field,
+ this.sortStatus.direction);
+ if (sortPermutation) {
+ var splicePermutation = deletePermutation.map(function(element) {
+ return element != -1 ? sortPermutation[element] : -1;
+ });
+ this.dispatchPermutedEvent_(splicePermutation);
+ } else {
+ this.dispatchPermutedEvent_(deletePermutation);
+ }
+ this.dispatchEvent(spliceEvent);
return rv;
},
@@ -105,9 +178,8 @@ cr.define('cr.ui', function() {
/**
* Use this to update a given item in the array. This does not remove and
* reinsert a new item.
- *
* This dispatches a change event.
- *
+ * This runs sort after updating.
* @param {number} index The index of the item to update.
*/
updateIndex: function(index) {
@@ -118,6 +190,151 @@ cr.define('cr.ui', function() {
var e = new Event('change');
e.index = index;
this.dispatchEvent(e);
+
+ if (this.sortStatus.field) {
+ var sortPermutation = this.doSort_(this.sortStatus.field,
+ this.sortStatus.direction);
+ if (sortPermutation)
+ this.dispatchPermutedEvent_(sortPermutation);
+ }
+ },
+
+ /**
+ * Creates sort status with given field and direction.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ * @return {!Object} Created sort status.
+ */
+ createSortStatus: function(field, direction) {
+ return {
+ field: field,
+ direction: direction
+ };
+ },
+
+ /**
+ * Called before a sort happens so that you may fetch additional data
+ * required for the sort.
+ *
+ * @param {string} field Sort field.
+ * @param {function()} callback The function to invoke when preparation
+ * is complete.
+ */
+ prepareSort: function(field, callback) {
+ callback();
+ },
+
+ /**
+ * Sorts data model according to given field and direction and dispathes
+ * sorted event.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ */
+ sort: function(field, direction) {
+ var self = this;
+
+ this.prepareSort(field, function() {
+ var sortPermutation = self.doSort_(field, direction);
+ if (sortPermutation)
+ self.dispatchPermutedEvent_(sortPermutation);
+ self.dispatchSortEvent_();
+ });
+ },
+
+ /**
+ * Sorts data model according to given field and direction.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ */
+ doSort_: function(field, direction) {
+ var compareFunction = this.sortFunction_(field, direction);
+ var positions = [];
+ for (var i = 0; i < this.length; i++) {
+ positions[this.indexes_[i]] = i;
+ }
+ this.indexes_.sort(compareFunction);
+ this.sortStatus_ = this.createSortStatus(field, direction);
+ var sortPermutation = [];
+ var changed = false;
+ for (var i = 0; i < this.length; i++) {
+ if (positions[this.indexes_[i]] != i)
+ changed = true;
+ sortPermutation[positions[this.indexes_[i]]] = i;
+ }
+ if (changed)
+ return sortPermutation;
+ return null;
+ },
+
+ dispatchSortEvent_: function() {
+ var e = new Event('sorted');
+ this.dispatchEvent(e);
+ },
+
+ dispatchPermutedEvent_: function(permutation) {
+ var e = new Event('permuted');
+ e.permutation = permutation;
+ e.newLength = this.length;
+ this.dispatchEvent(e);
+ },
+
+ /**
+ * Creates compare function for the field.
+ * Returns the function set as sortFunction for given field
+ * or default compare function
+ * @param {string} field Sort field.
+ * @param {function(*, *): number} Compare function.
+ */
+ createCompareFunction_: function(field) {
+ var compareFunction =
+ this.compareFunctions_ ? this.compareFunctions_[field] : null;
+ var defaultValuesCompareFunction = this.defaultValuesCompareFunction;
+ if (compareFunction) {
+ return compareFunction;
+ } else {
+ return function(a, b) {
+ return defaultValuesCompareFunction.call(null, a[field], b[field]);
+ }
+ }
+ return compareFunction;
+ },
+
+ /**
+ * Creates compare function for given field and direction.
+ * @param {string} field Sort field.
+ * @param {string} direction Sort direction.
+ * @param {function(*, *): number} Compare function.
+ */
+ sortFunction_: function(field, direction) {
+ var compareFunction = null;
+ if (field !== null)
+ compareFunction = this.createCompareFunction_(field);
+ var dirMultiplier = direction == 'desc' ? -1 : 1;
+
+ return function(index1, index2) {
+ var item1 = this.array_[index1];
+ var item2 = this.array_[index2];
+
+ var compareResult = 0;
+ if (typeof(compareFunction) === 'function')
+ compareResult = compareFunction.call(null, item1, item2);
+ if (compareResult != 0)
+ return dirMultiplier * compareResult;
+ return dirMultiplier * this.defaultValuesCompareFunction(index1,
+ index2);
+ }.bind(this);
+ },
+
+ /**
+ * Default compare function.
+ */
+ defaultValuesCompareFunction: function(a, b) {
+ // We could insert i18n comparisons here.
+ if (a < b)
+ return -1;
+ if (a > b)
+ return 1;
+ return 0;
}
};
diff --git a/chrome/browser/resources/shared/js/cr/ui/list.js b/chrome/browser/resources/shared/js/cr/ui/list.js
index d8dc94c9..5878ccd 100644
--- a/chrome/browser/resources/shared/js/cr/ui/list.js
+++ b/chrome/browser/resources/shared/js/cr/ui/list.js
@@ -160,26 +160,23 @@ cr.define('cr.ui', function() {
/**
* The data model driving the list.
- * @type {ListDataModel}
+ * @type {ArrayDataModel}
*/
set dataModel(dataModel) {
if (this.dataModel_ != dataModel) {
- if (!this.boundHandleDataModelSplice_) {
- this.boundHandleDataModelSplice_ =
- this.handleDataModelSplice_.bind(this);
+ if (!this.boundHandleDataModelPermuted_) {
+ this.boundHandleDataModelPermuted_ =
+ this.handleDataModelPermuted_.bind(this);
this.boundHandleDataModelChange_ =
this.handleDataModelChange_.bind(this);
- this.boundHandleSorted_ =
- this.handleSorted_.bind(this);
}
if (this.dataModel_) {
- this.dataModel_.removeEventListener('splice',
- this.boundHandleDataModelSplice_);
+ this.dataModel_.removeEventListener(
+ 'permuted',
+ this.boundHandleDataModelPermuted_);
this.dataModel_.removeEventListener('change',
this.boundHandleDataModelChange_);
- this.dataModel_.removeEventListener('sorted',
- this.boundHandleSorted_);
}
this.dataModel_ = dataModel;
@@ -187,15 +184,14 @@ cr.define('cr.ui', function() {
this.cachedItems_ = {};
this.selectionModel.clear();
if (dataModel)
- this.selectionModel.adjust(0, 0, dataModel.length);
+ this.selectionModel.adjustLength(dataModel.length);
if (this.dataModel_) {
- this.dataModel_.addEventListener('splice',
- this.boundHandleDataModelSplice_);
+ this.dataModel_.addEventListener(
+ 'permuted',
+ this.boundHandleDataModelPermuted_);
this.dataModel_.addEventListener('change',
this.boundHandleDataModelChange_);
- this.dataModel_.addEventListener('sorted',
- this.boundHandleSorted_);
}
this.redraw();
@@ -554,42 +550,48 @@ cr.define('cr.ui', function() {
}
},
- handleDataModelSplice_: function(e) {
- this.selectionModel.adjust(e.index, e.removed.length, e.added.length);
- // Remove the cache of everything above index.
+ /**
+ * This handles data model 'permuted' event.
+ * this event is dispatched as a part of sort or splice.
+ * We need to
+ * - adjust the cache.
+ * - adjust selection.
+ * - redraw.
+ * - scroll the list to show selection.
+ * It is important that the cache adjustment happens before selection model
+ * adjustments.
+ * @param {Event} e The 'permuted' event.
+ */
+ handleDataModelPermuted_: function(e) {
+ var newCachedItems = {};
for (var index in this.cachedItems_) {
- if (index >= e.index)
+ if (e.permutation[index] != -1)
+ newCachedItems[e.permutation[index]] = this.cachedItems_[index];
+ else
delete this.cachedItems_[index];
}
- this.redraw();
- },
+ this.cachedItems_ = newCachedItems;
- handleDataModelChange_: function(e) {
- if (e.index >= this.firstIndex_ && e.index < this.lastIndex_) {
- this.cachedItems_ = null;
- this.redraw();
- }
- },
+ this.startBatchUpdates();
- /**
- * This handles data model 'sorted' event.
- * After sorting we need to
- * - adjust selection.
- * - delete the cache.
- * - redraw all the items.
- * - scroll the list to show selection.
- * @param {Event} e The 'sorted' event.
- */
- handleSorted_: function(e) {
var sm = this.selectionModel;
- sm.adjustToReordering(e.sortPermutation);
+ sm.adjustLength(e.newLength);
+ sm.adjustToReordering(e.permutation);
+
+ this.endBatchUpdates();
- this.cachedItems_ = null;
- this.redraw();
if (sm.leadIndex != -1)
this.scrollIndexIntoView(sm.leadIndex);
},
+ handleDataModelChange_: function(e) {
+ if (e.index >= this.firstIndex_ && e.index < this.lastIndex_) {
+ if (this.cachedItems_[e.index])
+ delete this.cachedItems_[e.index];
+ this.redraw();
+ }
+ },
+
/**
* @param {number} index The index of the item.
* @return {number} The top position of the item inside the list, not taking
@@ -823,6 +825,7 @@ cr.define('cr.ui', function() {
var listItem;
var dataModel = this.dataModel;
+ window.l = this;
for (var y = firstIndex; y < lastIndex; y++) {
var dataItem = dataModel.item(y);
listItem = cachedItems[y] || this.createItem(dataItem);
@@ -931,6 +934,13 @@ cr.define('cr.ui', function() {
},
/**
+ * Invalidates list by removing cached items.
+ */
+ invalidate: function() {
+ this.cachedItems_ = {};
+ },
+
+ /**
* Redraws a single item.
* @param {number} index The row index to redraw.
*/
diff --git a/chrome/browser/resources/shared/js/cr/ui/list_selection_model.js b/chrome/browser/resources/shared/js/cr/ui/list_selection_model.js
index fc5710f..8c16d57 100644
--- a/chrome/browser/resources/shared/js/cr/ui/list_selection_model.js
+++ b/chrome/browser/resources/shared/js/cr/ui/list_selection_model.js
@@ -247,43 +247,25 @@ cr.define('cr.ui', function() {
* @param {!Array.<number>} permutation The reordering permutation.
*/
adjustToReordering: function(permutation) {
+ var oldLeadIndex = this.leadIndex;
+
+ var oldSelectedIndexes = this.selectedIndexes;
+ this.selectedIndexes = oldSelectedIndexes.map(function(oldIndex) {
+ return permutation[oldIndex];
+ }).filter(function(index) {
+ return index != -1;
+ });
+
+ if (oldLeadIndex != -1)
+ this.leadIndex = permutation[oldLeadIndex];
},
/**
- * Adjust the selection by adding or removing a certain numbers of items.
- * This should be called by the owner of the selection model as items are
- * added and removed from the underlying data model.
- * @param {number} index The index of the first change.
- * @param {number} itemsRemoved Number of items removed.
- * @param {number} itemsAdded Number of items added.
+ * Adjusts selection model length.
+ * @param {number} length New selection model length.
*/
- adjust: function(index, itemsRemoved, itemsAdded) {
- function getNewAdjustedIndex(i) {
- if (i >= index && i < index + itemsRemoved) {
- return index
- } else if (i >= index) {
- return i - itemsRemoved + itemsAdded;
- }
- return i;
- }
-
- this.length_ += itemsAdded - itemsRemoved;
-
- var newMap = [];
- for (var i in this.selectedIndexes_) {
- i = Number(i);
- if (i < index) {
- newMap[i] = true;
- } else if (i < index + itemsRemoved) {
- // noop
- } else {
- newMap[i + itemsAdded - itemsRemoved] = true;
- }
- }
- this.selectedIndexes_ = newMap;
-
- this.leadIndex = getNewAdjustedIndex(this.leadIndex);
- this.anchorIndex = getNewAdjustedIndex(this.anchorIndex);
+ adjustLength: function(length) {
+ this.length_ = length;
}
};
diff --git a/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js b/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js
index 119f0fb..2cf43a92 100644
--- a/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js
+++ b/chrome/browser/resources/shared/js/cr/ui/list_single_selection_model.js
@@ -197,35 +197,21 @@ cr.define('cr.ui', function() {
* @param {!Array.<number>} permutation The reordering permutation.
*/
adjustToReordering: function(permutation) {
+ if (this.leadIndex != -1)
+ this.leadIndex = permutation[this.leadIndex];
+
+ var oldSelectedIndex = this.selectedIndex;
+ if (oldSelectedIndex != -1) {
+ this.selectedIndex = permutation[oldSelectedIndex];
+ }
},
/**
- * Adjust the selection by adding or removing a certain numbers of items.
- * This should be called by the owner of the selection model as items are
- * added and removed from the underlying data model.
- * @param {number} index The index of the first change.
- * @param {number} itemsRemoved Number of items removed.
- * @param {number} itemsAdded Number of items added.
+ * Adjusts selection model length.
+ * @param {number} length New selection model length.
*/
- adjust: function(index, itemsRemoved, itemsAdded) {
- function getNewAdjustedIndex(i) {
- if (i >= index && i < index + itemsRemoved) {
- return index;
- } else if (i >= index) {
- return i + itemsAdded - itemsRemoved;
- }
- return i;
- }
-
- this.length_ += itemsAdded - itemsRemoved;
-
- var i = this.selectedIndex;
- if (itemsRemoved > 0 && i >= index && i < index + itemsRemoved)
- this.selectedIndex = -1;
- else if (i >= index)
- this.selectedIndex = i + itemsAdded - itemsRemoved;
-
- this.leadIndex = getNewAdjustedIndex(this.leadIndex);
+ adjustLength: function(length) {
+ this.length_ = length;
}
};
diff --git a/chrome/browser/resources/shared/js/cr/ui/table.js b/chrome/browser/resources/shared/js/cr/ui/table.js
index c23a02a..bd67378 100644
--- a/chrome/browser/resources/shared/js/cr/ui/table.js
+++ b/chrome/browser/resources/shared/js/cr/ui/table.js
@@ -7,7 +7,7 @@
*/
cr.define('cr.ui', function() {
- const TableSelectionModel = cr.ui.table.TableSelectionModel;
+ const ListSelectionModel = cr.ui.ListSelectionModel;
const ListSelectionController = cr.ui.ListSelectionController;
const ArrayDataModel = cr.ui.ArrayDataModel;
const TableColumnModel = cr.ui.table.TableColumnModel;
@@ -30,25 +30,19 @@ cr.define('cr.ui', function() {
/**
* The table data model.
*
- * @type {cr.ui.table.TableDataModel}
+ * @type {cr.ui.ArrayDataModel}
*/
get dataModel() {
return this.list_.dataModel;
},
set dataModel(dataModel) {
if (this.list_.dataModel != dataModel) {
- this.list_.dataModel = dataModel;
if (this.list_.dataModel) {
- this.list_.dataModel.removeEventListener('splice', this.boundRedraw_);
this.list_.dataModel.removeEventListener('sorted',
this.boundHandleSorted_);
}
this.list_.dataModel = dataModel;
- this.list_.dataModel.table = this;
-
-
if (this.list_.dataModel) {
- this.list_.dataModel.addEventListener('splice', this.boundRedraw_);
this.list_.dataModel.addEventListener('sorted',
this.boundHandleSorted_);
}
@@ -66,16 +60,13 @@ cr.define('cr.ui', function() {
},
set columnModel(columnModel) {
if (this.columnModel_ != columnModel) {
- if (this.columnModel_) {
- this.columnModel_.removeEventListener('change', this.boundRedraw_);
+ if (this.columnModel_)
this.columnModel_.removeEventListener('resize', this.boundResize_);
- }
this.columnModel_ = columnModel;
- if (this.columnModel_) {
- this.columnModel_.addEventListener('change', this.boundRedraw_);
+ if (this.columnModel_)
this.columnModel_.addEventListener('resize', this.boundResize_);
- }
+ this.list_.invalidate();
this.redraw();
}
},
@@ -84,7 +75,7 @@ cr.define('cr.ui', function() {
* The table selection model.
*
* @type
- * {cr.ui.table.TableSelectionModel|cr.ui.table.TableSingleSelectionModel}
+ * {cr.ui.ListSelectionModel|cr.ui.table.ListSingleSelectionModel}
*/
get selectionModel() {
return this.list_.selectionModel;
@@ -92,9 +83,8 @@ cr.define('cr.ui', function() {
set selectionModel(selectionModel) {
if (this.list_.selectionModel != selectionModel) {
if (this.dataModel)
- selectionModel.adjust(0, 0, this.dataModel.length);
+ selectionModel.adjustLength(this.dataModel.length);
this.list_.selectionModel = selectionModel;
- this.redraw();
}
},
@@ -114,7 +104,7 @@ cr.define('cr.ui', function() {
decorate: function() {
this.list_ = this.ownerDocument.createElement('list');
TableList.decorate(this.list_);
- this.list_.selectionModel = new TableSelectionModel(this);
+ this.list_.selectionModel = new ListSelectionModel(this);
this.list_.table = this;
this.header_ = this.ownerDocument.createElement('div');
@@ -127,7 +117,6 @@ cr.define('cr.ui', function() {
this.ownerDocument.defaultView.addEventListener(
'resize', this.header_.updateWidth.bind(this.header_));
- this.boundRedraw_ = this.redraw.bind(this);
this.boundResize_ = this.resize.bind(this);
this.boundHandleSorted_ = this.handleSorted_.bind(this);
@@ -139,6 +128,14 @@ cr.define('cr.ui', function() {
},
/**
+ * Redraws the table.
+ */
+ redraw: function(index) {
+ this.list_.redraw();
+ this.header_.redraw();
+ },
+
+ /**
* Resize the table columns.
*/
resize: function() {
@@ -166,36 +163,12 @@ cr.define('cr.ui', function() {
},
/**
- * Redraws the table.
- * This forces the list to remove all cached items.
- */
- redraw: function() {
- this.list_.startBatchUpdates();
- if (this.list_.dataModel) {
- for (var i = 0; i < this.list_.dataModel.length; i++) {
- this.list_.redrawItem(i);
- }
- }
- this.list_.endBatchUpdates();
- this.list_.redraw();
- this.header_.redraw();
- },
-
- /**
* This handles data model 'sorted' event.
- * After sorting we need to
- * - adjust selection
- * - redraw all the items
- * - scroll the list to show selection.
+ * After sorting we need to redraw header
* @param {Event} e The 'sorted' event.
*/
handleSorted_: function(e) {
- var sm = this.list_.selectionModel;
- sm.adjustToReordering(e.sortPermutation);
-
- this.redraw();
- if (sm.leadIndex != -1)
- this.list_.scrollIndexIntoView(sm.leadIndex)
+ this.header_.redraw();
},
/**
diff --git a/chrome/browser/resources/shared/js/cr/ui/table/table_data_model.js b/chrome/browser/resources/shared/js/cr/ui/table/table_data_model.js
deleted file mode 100644
index 311fd67..0000000
--- a/chrome/browser/resources/shared/js/cr/ui/table/table_data_model.js
+++ /dev/null
@@ -1,275 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview This is a table data model
- */
-cr.define('cr.ui.table', function() {
- const EventTarget = cr.EventTarget;
- const Event = cr.Event;
- const ArrayDataModel = cr.ui.ArrayDataModel;
-
- /**
- * A table data model that supports sorting by storing initial indexes of
- * elements for each position in sorted array.
- * @param {!Array} items The underlying array.
- * @constructor
- * @extends {ArrayDataModel}
- */
- function TableDataModel(items) {
- ArrayDataModel.apply(this, arguments);
- this.indexes_ = [];
- for (var i = 0; i < items.length; i++) {
- this.indexes_.push(i);
- }
- }
-
- TableDataModel.prototype = {
- __proto__: ArrayDataModel.prototype,
-
- /**
- * Returns the item at the given index.
- * This implementation returns the item at the given index in the source
- * array before sort.
- * @param {number} index The index of the element to get.
- * @return {*} The element at the given index.
- */
- getItemByUnsortedIndex_: function(unsortedIndex) {
- return ArrayDataModel.prototype.item.call(this, unsortedIndex);
- },
-
- /**
- * Returns the item at the given index.
- * This implementation returns the item at the given index in the sorted
- * array.
- * @param {number} index The index of the element to get.
- * @return {*} The element at the given index.
- */
- item: function(index) {
- if (index >= 0 && index < this.length)
- return this.getItemByUnsortedIndex_(this.indexes_[index]);
- return undefined;
- },
-
- /**
- * Returns compare function set for given field.
- * @param {string} field The field to get compare function for.
- * @return {Function(*, *): number} Compare function set for given field.
- */
- compareFunction: function(field) {
- return this.compareFunctions_[field];
- },
-
- /**
- * Sets compare function for given field.
- * @param {string} field The field to set compare function.
- * @param {Function(*, *): number} Compare function to set for given field.
- */
- setCompareFunction: function(field, compareFunction) {
- this.compareFunctions_[field] = compareFunction;
- },
-
- /**
- * Returns current sort status.
- * @return {!Object} Current sort status.
- */
- get sortStatus() {
- if (this.sortStatus_) {
- return this.createSortStatus(
- this.sortStatus_.field, this.sortStatus_.direction);
- } else {
- return this.createSortStatus(null, null);
- }
- },
-
- /**
- * This removes and adds items to the model.
- * This dispatches a splice event.
- * This implementation runs sort after splice and creates permutation for
- * the whole change.
- * @param {number} index The index of the item to update.
- * @param {number} deleteCount The number of items to remove.
- * @param {...*} The items to add.
- * @return {!Array} An array with the removed items.
- */
- splice: function(index, deleteCount, var_args) {
- var addCount = arguments.length - 2;
- var newIndexes = [];
- var deletePermutation = [];
- var deleted = 0;
- for (var i = 0; i < this.indexes_.length; i++) {
- var oldIndex = this.indexes_[i];
- if (oldIndex < index) {
- newIndexes.push(oldIndex);
- deletePermutation.push(i - deleted);
- } else if (oldIndex >= index + deleteCount) {
- newIndexes.push(oldIndex - deleteCount + addCount);
- deletePermutation.push(i - deleted);
- } else {
- deletePermutation.push(-1);
- deleted++;
- }
- }
- for (var i = 0; i < addCount; i++) {
- newIndexes.push(index + i);
- }
- this.indexes_ = newIndexes;
-
- var rv = ArrayDataModel.prototype.splice.apply(this, arguments);
-
- var splicePermutation;
- if (this.sortStatus.field) {
- var sortPermutation = this.doSort_(this.sortStatus.field,
- this.sortStatus.direction);
- splicePermutation = deletePermutation.map(function(element) {
- return element != -1 ? sortPermutation[element] : -1;
- });
- } else {
- splicePermutation = deletePermutation;
- }
- this.dispatchSortEvent_(splicePermutation);
-
- return rv;
- },
-
- /**
- * Use this to update a given item in the array. This does not remove and
- * reinsert a new item.
- * This dispatches a change event.
- * This implementation runs sort after updating.
- * @param {number} index The index of the item to update.
- */
- updateIndex: function(index) {
- ArrayDataModel.prototype.updateIndex.apply(this, arguments);
-
- if (this.sortStatus.field)
- this.sort(this.sortStatus.field, this.sortStatus.direction);
- },
-
- /**
- * Creates sort status with given field and direction.
- * @param {string} field Sort field.
- * @param {string} direction Sort direction.
- * @return {!Object} Created sort status.
- */
- createSortStatus: function(field, direction) {
- return {
- field: field,
- direction: direction
- };
- },
-
- /**
- * Called before a sort happens so that you may fetch additional data
- * required for the sort.
- *
- * @param {string} field Sort field.
- * @param {function()} callback The function to invoke when preparation
- * is complete.
- */
- prepareSort: function(field, callback) {
- callback();
- },
-
- /**
- * Sorts data model according to given field and direction and dispathes
- * sorted event.
- * @param {string} field Sort field.
- * @param {string} direction Sort direction.
- */
- sort: function(field, direction) {
- var self = this;
-
- this.prepareSort(field, function() {
- var sortPermutation = self.doSort_(field, direction);
- self.dispatchSortEvent_(sortPermutation);
- });
- },
-
- /**
- * Sorts data model according to given field and direction.
- * @param {string} field Sort field.
- * @param {string} direction Sort direction.
- */
- doSort_: function(field, direction) {
- var compareFunction = this.sortFunction_(field, direction);
- var positions = [];
- for (var i = 0; i < this.length; i++) {
- positions[this.indexes_[i]] = i;
- }
- this.indexes_.sort(compareFunction);
- this.sortStatus_ = this.createSortStatus(field, direction);
- var sortPermutation = [];
- for (var i = 0; i < this.length; i++) {
- sortPermutation[positions[this.indexes_[i]]] = i;
- }
- return sortPermutation;
- },
-
- dispatchSortEvent_: function(sortPermutation) {
- var e = new Event('sorted');
- e.sortPermutation = sortPermutation;
- this.dispatchEvent(e);
- },
-
- /**
- * Creates compare function for the field.
- * Returns the function set as sortFunction for given field
- * or default compare function
- * @param {string} field Sort field.
- * @param {Function(*, *): number} Compare function.
- */
- createCompareFunction_: function(field) {
- var compareFunction =
- this.compareFunctions_ ? this.compareFunctions_[field] : null;
- var defaultValuesCompareFunction = this.defaultValuesCompareFunction;
- if (compareFunction) {
- return compareFunction;
- } else {
- return function(a, b) {
- return defaultValuesCompareFunction.call(null, a[field], b[field]);
- }
- }
- return compareFunction;
- },
-
- /**
- * Creates compare function for given field and direction.
- * @param {string} field Sort field.
- * @param {string} direction Sort direction.
- * @param {Function(*, *): number} Compare function.
- */
- sortFunction_: function(field, direction) {
- var compareFunction = this.createCompareFunction_(field);
- var dirMultiplier = direction == 'desc' ? -1 : 1;
-
- return function(index1, index2) {
- var item1 = this.getItemByUnsortedIndex_(index1);
- var item2 = this.getItemByUnsortedIndex_(index2);
-
- var compareResult = compareFunction.call(null, item1, item2);
- if (compareResult != 0)
- return dirMultiplier * compareResult;
- return dirMultiplier * this.defaultValuesCompareFunction(index1,
- index2);
- }.bind(this);
- },
-
- /**
- * Default compare function.
- */
- defaultValuesCompareFunction: function(a, b) {
- // We could insert i18n comparisons here.
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
- }
- };
-
- return {
- TableDataModel: TableDataModel
- };
-});
diff --git a/chrome/browser/resources/shared/js/cr/ui/table/table_selection_model.js b/chrome/browser/resources/shared/js/cr/ui/table/table_selection_model.js
deleted file mode 100644
index d4a197a..0000000
--- a/chrome/browser/resources/shared/js/cr/ui/table/table_selection_model.js
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview This is a multiple selection model for table
- */
-cr.define('cr.ui.table', function() {
- const ListSelectionModel = cr.ui.ListSelectionModel;
-
- /**
- * Creates a new selection model that is to be used with tables.
- * This implementation supports multiple selection.
- * Selected items are stored, not indexes, so selections are preserved
- * after items reordering (e.g. because of sort).
- * @param {number=} opt_length The number of items in the selection.
- * @constructor
- * @extends {!cr.EventTarget}
- */
- function TableSelectionModel(opt_length) {
- ListSelectionModel.apply(this, arguments);
- }
-
- TableSelectionModel.prototype = {
- __proto__: ListSelectionModel.prototype,
-
-
- /**
- * Adjusts the selection after reordering of items in the table.
- * @param {!Array.<number>} permutation The reordering permutation.
- */
- adjustToReordering: function(permutation) {
- var oldLeadIndex = this.leadIndex;
-
- var oldSelectedIndexes = this.selectedIndexes;
- this.selectedIndexes = oldSelectedIndexes.map(function(oldIndex) {
- return permutation[oldIndex];
- }).filter(function(index) {
- return index != -1;
- });
-
- if (oldLeadIndex != -1)
- this.leadIndex = permutation[oldLeadIndex];
- },
-
- /**
- * Adjust the selection by adding or removing a certain numbers of items.
- * This should be called by the owner of the selection model as items are
- * added and removed from the underlying data model.
- * This implementation updates selection model length only. The actual
- * selected indexes changes are processed in adjustToReordering.
- * @param {number} index The index of the first change.
- * @param {number} itemsRemoved Number of items removed.
- * @param {number} itemsAdded Number of items added.
- */
- adjust: function(index, itemsRemoved, itemsAdded) {
- ListSelectionModel.prototype.adjust.call(
- this, this.length, itemsRemoved, itemsAdded);
- }
- };
-
- return {
- TableSelectionModel: TableSelectionModel
- };
-});
diff --git a/chrome/browser/resources/shared/js/cr/ui/table/table_single_selection_model.js b/chrome/browser/resources/shared/js/cr/ui/table/table_single_selection_model.js
deleted file mode 100644
index c1da65f..0000000
--- a/chrome/browser/resources/shared/js/cr/ui/table/table_single_selection_model.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview This is a single selection model for table
- */
-cr.define('cr.ui.table', function() {
- const ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
-
- /**
- * Creates a new selection model that is to be used with tables.
- * This implementation supports single selection.
- * Selected item is stored, not index, so selection is preserved
- * after items reordering (e.g. because of sort).
- * @param {number=} opt_length The number of items in the selection.
- * @constructor
- * @extends {!cr.EventTarget}
- */
- function TableSingleSelectionModel(opt_length) {
- ListSingleSelectionModel.apply(this, arguments);
- }
-
- TableSingleSelectionModel.prototype = {
- __proto__: ListSingleSelectionModel.prototype,
-
-
- /**
- * Adjusts the selection after reordering of items in the table.
- * @param {!Array.<number>} permutation The reordering permutation.
- */
- adjustToReordering: function(permutation) {
- if (this.leadIndex != -1)
- this.leadIndex = permutation[this.leadIndex];
-
- var oldSelectedIndex = this.selectedIndex;
- if (oldSelectedIndex != -1) {
- this.selectedIndex = permutation[oldSelectedIndex];
- }
- },
-
- /**
- * Adjust the selection by adding or removing a certain numbers of items.
- * This should be called by the owner of the selection model as items are
- * added and removed from the underlying data model.
- * @param {number} index The index of the first change.
- * @param {number} itemsRemoved Number of items removed.
- * @param {number} itemsAdded Number of items added.
- */
- adjust: function(index, itemsRemoved, itemsAdded) {
- ListSingleSelectionModel.prototype.adjust.call(
- this, this.length, itemsRemoved, itemsAdded);
- }
- };
-
- return {
- TableSingleSelectionModel: TableSingleSelectionModel
- };
-});
diff --git a/chrome/browser/resources/shared_resources.grd b/chrome/browser/resources/shared_resources.grd
index 525edf6..a66ece9 100644
--- a/chrome/browser/resources/shared_resources.grd
+++ b/chrome/browser/resources/shared_resources.grd
@@ -94,16 +94,10 @@ without changes to the corresponding grd file. paaaae -->
file="shared/js/cr/ui/table/table_column.js" type="BINDATA" />
<include name="IDR_SHARED_JS_CR_UI_TABLE_COLUMN_MODEL"
file="shared/js/cr/ui/table/table_column_model.js" type="BINDATA" />
- <include name="IDR_SHARED_JS_CR_UI_TABLE_DATA_MODEL"
- file="shared/js/cr/ui/table/table_data_model.js" type="BINDATA" />
<include name="IDR_SHARED_JS_CR_UI_TABLE_HEADER"
file="shared/js/cr/ui/table/table_header.js" type="BINDATA" />
<include name="IDR_SHARED_JS_CR_UI_TABLE_LIST"
file="shared/js/cr/ui/table/table_list.js" type="BINDATA" />
- <include name="IDR_SHARED_JS_CR_UI_TABLE_SELECTION_MODEL"
- file="shared/js/cr/ui/table/table_selection_model.js" type="BINDATA" />
- <include name="IDR_SHARED_JS_CR_UI_TABLE_SINGLE_SELECTION_MODEL"
- file="shared/js/cr/ui/table/table_single_selection_model.js" type="BINDATA" />
<include name="IDR_SHARED_JS_CR_UI_TABLE_SPLITTER"
file="shared/js/cr/ui/table/table_splitter.js" type="BINDATA" />
<include name="IDR_SHARED_JS_CR_UI_TABS"