1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochcr.define('cr.ui', function() {
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const Event = cr.Event;
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const EventTarget = cr.EventTarget;
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  /**
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick   * Creates a new selection model that is to be used with lists.
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   *
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @param {number=} opt_length The number items in the selection.
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   *
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @constructor
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   * @extends {!cr.EventTarget}
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch   */
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  function ListSelectionModel(opt_length) {
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    this.length_ = opt_length || 0;
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Even though selectedIndexes_ is really a map we use an array here to get
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // iteration in the order of the indexes.
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    this.selectedIndexes_ = [];
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListSelectionModel.prototype = {
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    __proto__: EventTarget.prototype,
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The number of items in the model.
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @type {number}
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    get length() {
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return this.length_;
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @type {!Array} The selected indexes.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    get selectedIndexes() {
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return Object.keys(this.selectedIndexes_).map(Number);
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    set selectedIndexes(selectedIndexes) {
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.beginChange();
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.unselectAll();
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (var i = 0; i < selectedIndexes.length; i++) {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.setIndexSelected(selectedIndexes[i], true);
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (selectedIndexes.length) {
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.leadIndex = this.anchorIndex = selectedIndexes[0];
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.leadIndex = this.anchorIndex = -1;
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.endChange();
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Convenience getter which returns the first selected index.
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @type {number}
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    get selectedIndex() {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (var i in this.selectedIndexes_) {
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return Number(i);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return -1;
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    set selectedIndex(selectedIndex) {
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.beginChange();
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.unselectAll();
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (selectedIndex != -1) {
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.selectedIndexes = [selectedIndex];
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.leadIndex = this.anchorIndex = -1;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.endChange();
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Selects a range of indexes, starting with {@code start} and ends with
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * {@code end}.
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @param {number} start The first index to select.
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @param {number} end The last index to select.
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    selectRange: function(start, end) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Swap if starts comes after end.
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (start > end) {
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        var tmp = start;
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        start = end;
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        end = tmp;
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.beginChange();
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (var index = start; index != end; index++) {
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.setIndexSelected(index, true);
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.setIndexSelected(end, true);
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.endChange();
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Selects all indexes.
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    selectAll: function() {
1043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.selectRange(0, this.length - 1);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Clears the selection
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    clear: function() {
1113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.beginChange();
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.length_ = 0;
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.anchorIndex = this.leadIndex = -1;
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.unselectAll();
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.endChange();
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * Unselects all selected items.
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    unselectAll: function() {
1223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.beginChange();
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (var i in this.selectedIndexes_) {
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.setIndexSelected(i, false);
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
1263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.endChange();
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Sets the selected state for an index.
1313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @param {number} index The index to set the selected state for.
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @param {boolean} b Whether to select the index or not.
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    setIndexSelected: function(index, b) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      var oldSelected = index in this.selectedIndexes_;
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (oldSelected == b)
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (b)
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.selectedIndexes_[index] = true;
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      else
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        delete this.selectedIndexes_[index];
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.beginChange();
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Changing back?
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (index in this.changedIndexes_ && this.changedIndexes_[index] == !b) {
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        delete this.changedIndexes_[index];
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.changedIndexes_[index] = b;
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // End change dispatches an event which in turn may update the view.
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      this.endChange();
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Whether a given index is selected or not.
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @param {number} index The index to check.
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @return {boolean} Whether an index is selected.
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    getIndexSelected: function(index) {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return index in this.selectedIndexes_;
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * This is used to begin batching changes. Call {@code endChange} when you
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * are done making changes.
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    beginChange: function() {
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!this.changeCount_) {
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.changeCount_ = 0;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.changedIndexes_ = {};
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.changeCount_++;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Call this after changes are done and it will dispatch a change event if
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * any changes were actually done.
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    endChange: function() {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.changeCount_--;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!this.changeCount_) {
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        var indexes = Object.keys(this.changedIndexes_);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (indexes.length) {
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          var e = new Event('change');
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          e.changes = indexes.map(function(index) {
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            return {
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              index: index,
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              selected: this.changedIndexes_[index]
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            };
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }, this);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          this.dispatchEvent(e);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        this.changedIndexes_ = {};
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    leadIndex_: -1,
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The leadIndex is used with multiple selection and it is the index that
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * the user is moving using the arrow keys.
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @type {number}
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    get leadIndex() {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return this.leadIndex_;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    set leadIndex(leadIndex) {
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      var li = Math.max(-1, Math.min(this.length_ - 1, leadIndex));
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (li != this.leadIndex_) {
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        var oldLeadIndex = this.leadIndex_;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.leadIndex_ = li;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        cr.dispatchPropertyChange(this, 'leadIndex', li, oldLeadIndex);
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    anchorIndex_: -1,
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * The anchorIndex is used with multiple selection.
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @type {number}
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    get anchorIndex() {
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return this.anchorIndex_;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    set anchorIndex(anchorIndex) {
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      var ai = Math.max(-1, Math.min(this.length_ - 1, anchorIndex));
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (ai != this.anchorIndex_) {
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        var oldAnchorIndex = this.anchorIndex_;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        this.anchorIndex_ = ai;
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        cr.dispatchPropertyChange(this, 'anchorIndex', ai, oldAnchorIndex);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    },
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    /**
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * Whether the selection model supports multiple selected items.
2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     * @type {boolean}
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick     */
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    get multiple() {
2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return true;
2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    },
2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    /**
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * Adjusts the selection after reordering of items in the table.
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     * @param {!Array.<number>} permutation The reordering permutation.
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen     */
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    adjustToReordering: function(permutation) {
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    },
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    /**
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * Adjust the selection by adding or removing a certain numbers of items.
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * This should be called by the owner of the selection model as items are
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * added and removed from the underlying data model.
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @param {number} index The index of the first change.
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @param {number} itemsRemoved Number of items removed.
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     * @param {number} itemsAdded Number of items added.
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     */
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    adjust: function(index, itemsRemoved, itemsAdded) {
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      function getNewAdjustedIndex(i) {
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        if (i >= index && i < index + itemsRemoved) {
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          return index
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else if (i >= index) {
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          return i - itemsRemoved + itemsAdded;
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return i;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.length_ += itemsAdded - itemsRemoved;
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      var newMap = [];
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (var i in this.selectedIndexes_) {
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        i = Number(i);
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (i < index) {
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          newMap[i] = true;
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else if (i < index + itemsRemoved) {
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // noop
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          newMap[i + itemsAdded - itemsRemoved] = true;
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.selectedIndexes_ = newMap;
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.leadIndex = getNewAdjustedIndex(this.leadIndex);
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      this.anchorIndex = getNewAdjustedIndex(this.anchorIndex);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ListSelectionModel: ListSelectionModel
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch});
294