| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 cr.define('cr.ui', function() { | 5 cr.define('cr.ui', function() { |
| 6 /** | 6 /** |
| 7 * Creates a selection controller that is to be used with lists. This is | 7 * Creates a selection controller that is to be used with lists. This is |
| 8 * implemented for vertical lists but changing the behavior for horizontal | 8 * implemented for vertical lists but changing the behavior for horizontal |
| 9 * lists or icon views is a matter of overriding {@code getIndexBefore}, | 9 * lists or icon views is a matter of overriding {@code getIndexBefore}, |
| 10 * {@code getIndexAfter}, {@code getIndexAbove} as well as | 10 * {@code getIndexAfter}, {@code getIndexAbove} as well as |
| 11 * {@code getIndexBelow}. | 11 * {@code getIndexBelow}. |
| 12 * | 12 * |
| 13 * @param {cr.ui.ListSelectionModel} selectionModel The selection model to | 13 * @param {cr.ui.ListSelectionModel} selectionModel The selection model to |
| 14 * interact with. | 14 * interact with. |
| 15 * | 15 * |
| 16 * @constructor | 16 * @constructor |
| 17 * @extends {cr.EventTarget} | 17 * @extends {cr.EventTarget} |
| 18 */ | 18 */ |
| 19 function ListSelectionController(selectionModel) { | 19 function ListSelectionController(selectionModel) { |
| 20 this.selectionModel_ = selectionModel; | 20 this.selectionModel_ = selectionModel; |
| 21 } | 21 } |
| 22 | 22 |
| 23 ListSelectionController.prototype = { | 23 ListSelectionController.prototype = { |
| 24 | 24 |
| 25 /** | 25 /** |
| 26 * The selection model we are interacting with. | 26 * The selection model we are interacting with. |
| 27 * @type {cr.ui.ListSelectionModel} | 27 * @type {cr.ui.ListSelectionModel} |
| 28 */ | 28 */ |
| 29 get selectionModel() { | 29 get selectionModel() { return this.selectionModel_; }, |
| 30 return this.selectionModel_; | |
| 31 }, | |
| 32 | 30 |
| 33 /** | 31 /** |
| 34 * Returns the index below (y axis) the given element. | 32 * Returns the index below (y axis) the given element. |
| 35 * @param {number} index The index to get the index below. | 33 * @param {number} index The index to get the index below. |
| 36 * @return {number} The index below or -1 if not found. | 34 * @return {number} The index below or -1 if not found. |
| 37 */ | 35 */ |
| 38 getIndexBelow: function(index) { | 36 getIndexBelow: function(index) { |
| 39 if (index == this.getLastIndex()) | 37 if (index == this.getLastIndex()) |
| 40 return -1; | 38 return -1; |
| 41 return index + 1; | 39 return index + 1; |
| 42 }, | 40 }, |
| 43 | 41 |
| 44 /** | 42 /** |
| 45 * Returns the index above (y axis) the given element. | 43 * Returns the index above (y axis) the given element. |
| 46 * @param {number} index The index to get the index above. | 44 * @param {number} index The index to get the index above. |
| 47 * @return {number} The index below or -1 if not found. | 45 * @return {number} The index below or -1 if not found. |
| 48 */ | 46 */ |
| 49 getIndexAbove: function(index) { | 47 getIndexAbove: function(index) { return index - 1; }, |
| 50 return index - 1; | |
| 51 }, | |
| 52 | 48 |
| 53 /** | 49 /** |
| 54 * Returns the index before (x axis) the given element. This returns -1 | 50 * Returns the index before (x axis) the given element. This returns -1 |
| 55 * by default but override this for icon view and horizontal selection | 51 * by default but override this for icon view and horizontal selection |
| 56 * models. | 52 * models. |
| 57 * | 53 * |
| 58 * @param {number} index The index to get the index before. | 54 * @param {number} index The index to get the index before. |
| 59 * @return {number} The index before or -1 if not found. | 55 * @return {number} The index before or -1 if not found. |
| 60 */ | 56 */ |
| 61 getIndexBefore: function(index) { | 57 getIndexBefore: function(index) { return -1; }, |
| 62 return -1; | |
| 63 }, | |
| 64 | 58 |
| 65 /** | 59 /** |
| 66 * Returns the index after (x axis) the given element. This returns -1 | 60 * Returns the index after (x axis) the given element. This returns -1 |
| 67 * by default but override this for icon view and horizontal selection | 61 * by default but override this for icon view and horizontal selection |
| 68 * models. | 62 * models. |
| 69 * | 63 * |
| 70 * @param {number} index The index to get the index after. | 64 * @param {number} index The index to get the index after. |
| 71 * @return {number} The index after or -1 if not found. | 65 * @return {number} The index after or -1 if not found. |
| 72 */ | 66 */ |
| 73 getIndexAfter: function(index) { | 67 getIndexAfter: function(index) { return -1; }, |
| 74 return -1; | |
| 75 }, | |
| 76 | 68 |
| 77 /** | 69 /** |
| 78 * Returns the next list index. This is the next logical and should not | 70 * Returns the next list index. This is the next logical and should not |
| 79 * depend on any kind of layout of the list. | 71 * depend on any kind of layout of the list. |
| 80 * @param {number} index The index to get the next index for. | 72 * @param {number} index The index to get the next index for. |
| 81 * @return {number} The next index or -1 if not found. | 73 * @return {number} The next index or -1 if not found. |
| 82 */ | 74 */ |
| 83 getNextIndex: function(index) { | 75 getNextIndex: function(index) { |
| 84 if (index == this.getLastIndex()) | 76 if (index == this.getLastIndex()) |
| 85 return -1; | 77 return -1; |
| 86 return index + 1; | 78 return index + 1; |
| 87 }, | 79 }, |
| 88 | 80 |
| 89 /** | 81 /** |
| 90 * Returns the prevous list index. This is the previous logical and should | 82 * Returns the prevous list index. This is the previous logical and should |
| 91 * not depend on any kind of layout of the list. | 83 * not depend on any kind of layout of the list. |
| 92 * @param {number} index The index to get the previous index for. | 84 * @param {number} index The index to get the previous index for. |
| 93 * @return {number} The previous index or -1 if not found. | 85 * @return {number} The previous index or -1 if not found. |
| 94 */ | 86 */ |
| 95 getPreviousIndex: function(index) { | 87 getPreviousIndex: function(index) { return index - 1; }, |
| 96 return index - 1; | |
| 97 }, | |
| 98 | 88 |
| 99 /** | 89 /** |
| 100 * @return {number} The first index. | 90 * @return {number} The first index. |
| 101 */ | 91 */ |
| 102 getFirstIndex: function() { | 92 getFirstIndex: function() { return 0; }, |
| 103 return 0; | |
| 104 }, | |
| 105 | 93 |
| 106 /** | 94 /** |
| 107 * @return {number} The last index. | 95 * @return {number} The last index. |
| 108 */ | 96 */ |
| 109 getLastIndex: function() { | 97 getLastIndex: function() { return this.selectionModel.length - 1; }, |
| 110 return this.selectionModel.length - 1; | |
| 111 }, | |
| 112 | 98 |
| 113 /** | 99 /** |
| 114 * Called by the view when the user does a mousedown or mouseup on the | 100 * Called by the view when the user does a mousedown or mouseup on the |
| 115 * list. | 101 * list. |
| 116 * @param {!Event} e The browser mouse event. | 102 * @param {!Event} e The browser mouse event. |
| 117 * @param {number} index The index that was under the mouse pointer, -1 if | 103 * @param {number} index The index that was under the mouse pointer, -1 if |
| 118 * none. | 104 * none. |
| 119 */ | 105 */ |
| 120 handlePointerDownUp: function(e, index) { | 106 handlePointerDownUp: function(e, index) { |
| 121 var sm = this.selectionModel; | 107 var sm = this.selectionModel; |
| 122 var anchorIndex = sm.anchorIndex; | 108 var anchorIndex = sm.anchorIndex; |
| 123 var isDown = (e.type == 'mousedown'); | 109 var isDown = (e.type == 'mousedown'); |
| 124 | 110 |
| 125 sm.beginChange(); | 111 sm.beginChange(); |
| 126 | 112 |
| 127 if (index == -1) { | 113 if (index == -1) { |
| 128 // On Mac we always clear the selection if the user clicks a blank area. | 114 // On Mac we always clear the selection if the user clicks a blank area. |
| 129 // On Windows, we only clear the selection if neither Shift nor Ctrl are | 115 // On Windows, we only clear the selection if neither Shift nor Ctrl are |
| 130 // pressed. | 116 // pressed. |
| 131 if (cr.isMac || cr.isChromeOS) { | 117 if (cr.isMac || cr.isChromeOS) { |
| 132 sm.leadIndex = sm.anchorIndex = -1; | 118 sm.leadIndex = sm.anchorIndex = -1; |
| 133 sm.unselectAll(); | 119 sm.unselectAll(); |
| 134 } else if (!isDown && !e.shiftKey && !e.ctrlKey) | 120 } else if (!isDown && !e.shiftKey && !e.ctrlKey) |
| 135 // Keep anchor and lead indexes. Note that this is intentionally | 121 // Keep anchor and lead indexes. Note that this is intentionally |
| 136 // different than on the Mac. | 122 // different than on the Mac. |
| 137 if (sm.multiple) | 123 if (sm.multiple) |
| 138 sm.unselectAll(); | 124 sm.unselectAll(); |
| 139 } else { | 125 } else { |
| 140 if (sm.multiple && (cr.isMac ? e.metaKey : | 126 if (sm.multiple && |
| 141 (e.ctrlKey && !e.shiftKey))) { | 127 (cr.isMac ? e.metaKey : (e.ctrlKey && !e.shiftKey))) { |
| 142 // Selection is handled at mouseUp on windows/linux, mouseDown on mac. | 128 // Selection is handled at mouseUp on windows/linux, mouseDown on mac. |
| 143 if (cr.isMac ? isDown : !isDown) { | 129 if (cr.isMac ? isDown : !isDown) { |
| 144 // Toggle the current one and make it anchor index. | 130 // Toggle the current one and make it anchor index. |
| 145 sm.setIndexSelected(index, !sm.getIndexSelected(index)); | 131 sm.setIndexSelected(index, !sm.getIndexSelected(index)); |
| 146 sm.leadIndex = index; | 132 sm.leadIndex = index; |
| 147 sm.anchorIndex = index; | 133 sm.anchorIndex = index; |
| 148 } | 134 } |
| 149 } else if (e.shiftKey && anchorIndex != -1 && anchorIndex != index) { | 135 } else if (e.shiftKey && anchorIndex != -1 && anchorIndex != index) { |
| 150 // Shift is done in mousedown. | 136 // Shift is done in mousedown. |
| 151 if (isDown) { | 137 if (isDown) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 180 var tagName = e.target.tagName; | 166 var tagName = e.target.tagName; |
| 181 // If focus is in an input field of some kind, only handle navigation keys | 167 // If focus is in an input field of some kind, only handle navigation keys |
| 182 // that aren't likely to conflict with input interaction (e.g., text | 168 // that aren't likely to conflict with input interaction (e.g., text |
| 183 // editing, or changing the value of a checkbox or select). | 169 // editing, or changing the value of a checkbox or select). |
| 184 if (tagName == 'INPUT') { | 170 if (tagName == 'INPUT') { |
| 185 var inputType = e.target.type; | 171 var inputType = e.target.type; |
| 186 // Just protect space (for toggling) for checkbox and radio. | 172 // Just protect space (for toggling) for checkbox and radio. |
| 187 if (inputType == 'checkbox' || inputType == 'radio') { | 173 if (inputType == 'checkbox' || inputType == 'radio') { |
| 188 if (e.key == ' ') | 174 if (e.key == ' ') |
| 189 return; | 175 return; |
| 190 // Protect all but the most basic navigation commands in anything else. | 176 // Protect all but the most basic navigation commands in anything |
| 177 // else. |
| 191 } else if (e.key != 'ArrowUp' && e.key != 'ArrowDown') { | 178 } else if (e.key != 'ArrowUp' && e.key != 'ArrowDown') { |
| 192 return; | 179 return; |
| 193 } | 180 } |
| 194 } | 181 } |
| 195 // Similarly, don't interfere with select element handling. | 182 // Similarly, don't interfere with select element handling. |
| 196 if (tagName == 'SELECT') | 183 if (tagName == 'SELECT') |
| 197 return; | 184 return; |
| 198 | 185 |
| 199 var sm = this.selectionModel; | 186 var sm = this.selectionModel; |
| 200 var newIndex = -1; | 187 var newIndex = -1; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 220 } | 207 } |
| 221 | 208 |
| 222 switch (e.key) { | 209 switch (e.key) { |
| 223 case 'Home': | 210 case 'Home': |
| 224 newIndex = this.getFirstIndex(); | 211 newIndex = this.getFirstIndex(); |
| 225 break; | 212 break; |
| 226 case 'End': | 213 case 'End': |
| 227 newIndex = this.getLastIndex(); | 214 newIndex = this.getLastIndex(); |
| 228 break; | 215 break; |
| 229 case 'ArrowUp': | 216 case 'ArrowUp': |
| 230 newIndex = leadIndex == -1 ? | 217 newIndex = leadIndex == -1 ? this.getLastIndex() : |
| 231 this.getLastIndex() : this.getIndexAbove(leadIndex); | 218 this.getIndexAbove(leadIndex); |
| 232 break; | 219 break; |
| 233 case 'ArrowDown': | 220 case 'ArrowDown': |
| 234 newIndex = leadIndex == -1 ? | 221 newIndex = leadIndex == -1 ? this.getFirstIndex() : |
| 235 this.getFirstIndex() : this.getIndexBelow(leadIndex); | 222 this.getIndexBelow(leadIndex); |
| 236 break; | 223 break; |
| 237 case 'ArrowLeft': | 224 case 'ArrowLeft': |
| 238 case 'MediaPreviousTrack': | 225 case 'MediaPreviousTrack': |
| 239 newIndex = leadIndex == -1 ? | 226 newIndex = leadIndex == -1 ? this.getLastIndex() : |
| 240 this.getLastIndex() : this.getIndexBefore(leadIndex); | 227 this.getIndexBefore(leadIndex); |
| 241 break; | 228 break; |
| 242 case 'ArrowRight': | 229 case 'ArrowRight': |
| 243 case 'MediaNextTrack': | 230 case 'MediaNextTrack': |
| 244 newIndex = leadIndex == -1 ? | 231 newIndex = leadIndex == -1 ? this.getFirstIndex() : |
| 245 this.getFirstIndex() : this.getIndexAfter(leadIndex); | 232 this.getIndexAfter(leadIndex); |
| 246 break; | 233 break; |
| 247 default: | 234 default: |
| 248 prevent = false; | 235 prevent = false; |
| 249 } | 236 } |
| 250 | 237 |
| 251 if (newIndex != -1) { | 238 if (newIndex != -1) { |
| 252 sm.beginChange(); | 239 sm.beginChange(); |
| 253 | 240 |
| 254 sm.leadIndex = newIndex; | 241 sm.leadIndex = newIndex; |
| 255 if (e.shiftKey) { | 242 if (e.shiftKey) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 273 } | 260 } |
| 274 | 261 |
| 275 sm.endChange(); | 262 sm.endChange(); |
| 276 | 263 |
| 277 if (prevent) | 264 if (prevent) |
| 278 e.preventDefault(); | 265 e.preventDefault(); |
| 279 } | 266 } |
| 280 } | 267 } |
| 281 }; | 268 }; |
| 282 | 269 |
| 283 return { | 270 return {ListSelectionController: ListSelectionController}; |
| 284 ListSelectionController: ListSelectionController | |
| 285 }; | |
| 286 }); | 271 }); |
| OLD | NEW |