OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // require: array_data_model.js | 5 // require: array_data_model.js |
6 // require: list_selection_model.js | 6 // require: list_selection_model.js |
7 // require: list_selection_controller.js | 7 // require: list_selection_controller.js |
8 // require: list_item.js | 8 // require: list_item.js |
9 | 9 |
10 /** | 10 /** |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 this.itemConstructor_ = func; | 153 this.itemConstructor_ = func; |
154 this.cachedItems_ = {}; | 154 this.cachedItems_ = {}; |
155 this.redraw(); | 155 this.redraw(); |
156 } | 156 } |
157 }, | 157 }, |
158 | 158 |
159 dataModel_: null, | 159 dataModel_: null, |
160 | 160 |
161 /** | 161 /** |
162 * The data model driving the list. | 162 * The data model driving the list. |
163 * @type {ListDataModel} | 163 * @type {ArrayDataModel} |
164 */ | 164 */ |
165 set dataModel(dataModel) { | 165 set dataModel(dataModel) { |
166 if (this.dataModel_ != dataModel) { | 166 if (this.dataModel_ != dataModel) { |
167 if (!this.boundHandleDataModelSplice_) { | 167 if (!this.boundHandleDataModelPermuted_) { |
168 this.boundHandleDataModelSplice_ = | 168 this.boundHandleDataModelPermuted_ = |
169 this.handleDataModelSplice_.bind(this); | 169 this.handleDataModelPermuted_.bind(this); |
170 this.boundHandleDataModelChange_ = | 170 this.boundHandleDataModelChange_ = |
171 this.handleDataModelChange_.bind(this); | 171 this.handleDataModelChange_.bind(this); |
172 this.boundHandleSorted_ = | |
173 this.handleSorted_.bind(this); | |
174 } | 172 } |
175 | 173 |
176 if (this.dataModel_) { | 174 if (this.dataModel_) { |
177 this.dataModel_.removeEventListener('splice', | 175 this.dataModel_.removeEventListener( |
178 this.boundHandleDataModelSplice_); | 176 'permuted', |
| 177 this.boundHandleDataModelPermuted_); |
179 this.dataModel_.removeEventListener('change', | 178 this.dataModel_.removeEventListener('change', |
180 this.boundHandleDataModelChange_); | 179 this.boundHandleDataModelChange_); |
181 this.dataModel_.removeEventListener('sorted', | |
182 this.boundHandleSorted_); | |
183 } | 180 } |
184 | 181 |
185 this.dataModel_ = dataModel; | 182 this.dataModel_ = dataModel; |
186 | 183 |
187 this.cachedItems_ = {}; | 184 this.cachedItems_ = {}; |
188 this.selectionModel.clear(); | 185 this.selectionModel.clear(); |
189 if (dataModel) | 186 if (dataModel) |
190 this.selectionModel.adjust(0, 0, dataModel.length); | 187 this.selectionModel.adjustLength(dataModel.length); |
191 | 188 |
192 if (this.dataModel_) { | 189 if (this.dataModel_) { |
193 this.dataModel_.addEventListener('splice', | 190 this.dataModel_.addEventListener( |
194 this.boundHandleDataModelSplice_); | 191 'permuted', |
| 192 this.boundHandleDataModelPermuted_); |
195 this.dataModel_.addEventListener('change', | 193 this.dataModel_.addEventListener('change', |
196 this.boundHandleDataModelChange_); | 194 this.boundHandleDataModelChange_); |
197 this.dataModel_.addEventListener('sorted', | |
198 this.boundHandleSorted_); | |
199 } | 195 } |
200 | 196 |
201 this.redraw(); | 197 this.redraw(); |
202 } | 198 } |
203 }, | 199 }, |
204 | 200 |
205 get dataModel() { | 201 get dataModel() { |
206 return this.dataModel_; | 202 return this.dataModel_; |
207 }, | 203 }, |
208 | 204 |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 // the bottom of the list is not "sticky.") So, we set a timeout to | 543 // the bottom of the list is not "sticky.") So, we set a timeout to |
548 // rescroll the list after this all gets sorted out. This is perhaps | 544 // rescroll the list after this all gets sorted out. This is perhaps |
549 // not the most elegant solution, but no others seem obvious. | 545 // not the most elegant solution, but no others seem obvious. |
550 var self = this; | 546 var self = this; |
551 window.setTimeout(function() { | 547 window.setTimeout(function() { |
552 self.scrollIndexIntoView(pe.newValue); | 548 self.scrollIndexIntoView(pe.newValue); |
553 }); | 549 }); |
554 } | 550 } |
555 }, | 551 }, |
556 | 552 |
557 handleDataModelSplice_: function(e) { | 553 /** |
558 this.selectionModel.adjust(e.index, e.removed.length, e.added.length); | 554 * This handles data model 'permuted' event. |
559 // Remove the cache of everything above index. | 555 * this event is dispatched as a part of sort or splice. |
| 556 * We need to |
| 557 * - adjust the cache. |
| 558 * - adjust selection. |
| 559 * - redraw. |
| 560 * - scroll the list to show selection. |
| 561 * It is important that the cache adjustment happens before selection model |
| 562 * adjustments. |
| 563 * @param {Event} e The 'permuted' event. |
| 564 */ |
| 565 handleDataModelPermuted_: function(e) { |
| 566 var newCachedItems = {}; |
560 for (var index in this.cachedItems_) { | 567 for (var index in this.cachedItems_) { |
561 if (index >= e.index) | 568 if (e.permutation[index] != -1) |
| 569 newCachedItems[e.permutation[index]] = this.cachedItems_[index]; |
| 570 else |
562 delete this.cachedItems_[index]; | 571 delete this.cachedItems_[index]; |
563 } | 572 } |
564 this.redraw(); | 573 this.cachedItems_ = newCachedItems; |
| 574 |
| 575 this.startBatchUpdates(); |
| 576 |
| 577 var sm = this.selectionModel; |
| 578 sm.adjustLength(e.newLength); |
| 579 sm.adjustToReordering(e.permutation); |
| 580 |
| 581 this.endBatchUpdates(); |
| 582 |
| 583 if (sm.leadIndex != -1) |
| 584 this.scrollIndexIntoView(sm.leadIndex); |
565 }, | 585 }, |
566 | 586 |
567 handleDataModelChange_: function(e) { | 587 handleDataModelChange_: function(e) { |
568 if (e.index >= this.firstIndex_ && e.index < this.lastIndex_) { | 588 if (e.index >= this.firstIndex_ && e.index < this.lastIndex_) { |
569 this.cachedItems_ = null; | 589 if (this.cachedItems_[e.index]) |
| 590 delete this.cachedItems_[e.index]; |
570 this.redraw(); | 591 this.redraw(); |
571 } | 592 } |
572 }, | 593 }, |
573 | 594 |
574 /** | 595 /** |
575 * This handles data model 'sorted' event. | |
576 * After sorting we need to | |
577 * - adjust selection. | |
578 * - delete the cache. | |
579 * - redraw all the items. | |
580 * - scroll the list to show selection. | |
581 * @param {Event} e The 'sorted' event. | |
582 */ | |
583 handleSorted_: function(e) { | |
584 var sm = this.selectionModel; | |
585 sm.adjustToReordering(e.sortPermutation); | |
586 | |
587 this.cachedItems_ = null; | |
588 this.redraw(); | |
589 if (sm.leadIndex != -1) | |
590 this.scrollIndexIntoView(sm.leadIndex); | |
591 }, | |
592 | |
593 /** | |
594 * @param {number} index The index of the item. | 596 * @param {number} index The index of the item. |
595 * @return {number} The top position of the item inside the list, not taking | 597 * @return {number} The top position of the item inside the list, not taking |
596 * into account lead item. May vary in the case of multiple columns. | 598 * into account lead item. May vary in the case of multiple columns. |
597 */ | 599 */ |
598 getItemTop: function(index) { | 600 getItemTop: function(index) { |
599 return index * this.getItemHeight_(); | 601 return index * this.getItemHeight_(); |
600 }, | 602 }, |
601 | 603 |
602 /** | 604 /** |
603 * @param {number} index The index of the item. | 605 * @param {number} index The index of the item. |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 * Adds items to the list and {@code newCachedItems}. | 818 * Adds items to the list and {@code newCachedItems}. |
817 * @param {number} firstIndex The index of first item, inclusively. | 819 * @param {number} firstIndex The index of first item, inclusively. |
818 * @param {number} lastIndex The index of last item, exclusively. | 820 * @param {number} lastIndex The index of last item, exclusively. |
819 * @param {Object.<string, ListItem>} cachedItems Old items cache. | 821 * @param {Object.<string, ListItem>} cachedItems Old items cache. |
820 * @param {Object.<string, ListItem>} newCachedItems New items cache. | 822 * @param {Object.<string, ListItem>} newCachedItems New items cache. |
821 */ | 823 */ |
822 addItems: function(firstIndex, lastIndex, cachedItems, newCachedItems) { | 824 addItems: function(firstIndex, lastIndex, cachedItems, newCachedItems) { |
823 var listItem; | 825 var listItem; |
824 var dataModel = this.dataModel; | 826 var dataModel = this.dataModel; |
825 | 827 |
| 828 window.l = this; |
826 for (var y = firstIndex; y < lastIndex; y++) { | 829 for (var y = firstIndex; y < lastIndex; y++) { |
827 var dataItem = dataModel.item(y); | 830 var dataItem = dataModel.item(y); |
828 listItem = cachedItems[y] || this.createItem(dataItem); | 831 listItem = cachedItems[y] || this.createItem(dataItem); |
829 listItem.listIndex = y; | 832 listItem.listIndex = y; |
830 this.appendChild(listItem); | 833 this.appendChild(listItem); |
831 newCachedItems[y] = listItem; | 834 newCachedItems[y] = listItem; |
832 } | 835 } |
833 }, | 836 }, |
834 | 837 |
835 /** | 838 /** |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 var list = this; | 927 var list = this; |
925 window.setTimeout(function() { | 928 window.setTimeout(function() { |
926 if (listItem.parentNode == list) { | 929 if (listItem.parentNode == list) { |
927 list.measured_ = measureItem(list, listItem); | 930 list.measured_ = measureItem(list, listItem); |
928 } | 931 } |
929 }); | 932 }); |
930 } | 933 } |
931 }, | 934 }, |
932 | 935 |
933 /** | 936 /** |
| 937 * Invalidates list by removing cached items. |
| 938 */ |
| 939 invalidate: function() { |
| 940 this.cachedItems_ = {}; |
| 941 }, |
| 942 |
| 943 /** |
934 * Redraws a single item. | 944 * Redraws a single item. |
935 * @param {number} index The row index to redraw. | 945 * @param {number} index The row index to redraw. |
936 */ | 946 */ |
937 redrawItem: function(index) { | 947 redrawItem: function(index) { |
938 if (index >= this.firstIndex_ && index < this.lastIndex_) { | 948 if (index >= this.firstIndex_ && index < this.lastIndex_) { |
939 delete this.cachedItems_[index]; | 949 delete this.cachedItems_[index]; |
940 this.redraw(); | 950 this.redraw(); |
941 } | 951 } |
942 }, | 952 }, |
943 | 953 |
(...skipping 13 matching lines...) Expand all Loading... |
957 * because list items can contain controls that can be focused, and for some | 967 * because list items can contain controls that can be focused, and for some |
958 * purposes (e.g., styling), the list can still be conceptually focused at | 968 * purposes (e.g., styling), the list can still be conceptually focused at |
959 * that point even though it doesn't actually have the page focus. | 969 * that point even though it doesn't actually have the page focus. |
960 */ | 970 */ |
961 cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); | 971 cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); |
962 | 972 |
963 return { | 973 return { |
964 List: List | 974 List: List |
965 } | 975 } |
966 }); | 976 }); |
OLD | NEW |