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 // require: list_selection_model.js | 5 // require: list_selection_model.js |
6 // require: list_selection_controller.js | 6 // require: list_selection_controller.js |
7 // require: list.js | 7 // require: list.js |
8 | 8 |
9 /** | 9 /** |
10 * @fileoverview This implements a grid control. Grid contains a bunch of | 10 * @fileoverview This implements a grid control. Grid contains a bunch of |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 * @type {function(new:cr.ui.GridItem, *)} | 66 * @type {function(new:cr.ui.GridItem, *)} |
67 * @override | 67 * @override |
68 */ | 68 */ |
69 itemConstructor_: GridItem, | 69 itemConstructor_: GridItem, |
70 | 70 |
71 /** | 71 /** |
72 * Whether or not the rows on list have various heights. | 72 * Whether or not the rows on list have various heights. |
73 * Shows a warning at the setter because cr.ui.Grid does not support this. | 73 * Shows a warning at the setter because cr.ui.Grid does not support this. |
74 * @type {boolean} | 74 * @type {boolean} |
75 */ | 75 */ |
76 get fixedHeight() { | 76 get fixedHeight() { return true; }, |
77 return true; | |
78 }, | |
79 set fixedHeight(fixedHeight) { | 77 set fixedHeight(fixedHeight) { |
80 if (!fixedHeight) | 78 if (!fixedHeight) |
81 console.warn('cr.ui.Grid does not support fixedHeight = false'); | 79 console.warn('cr.ui.Grid does not support fixedHeight = false'); |
82 }, | 80 }, |
83 | 81 |
84 /** | 82 /** |
85 * @return {number} The number of columns determined by width of the grid | 83 * @return {number} The number of columns determined by width of the grid |
86 * and width of the items. | 84 * and width of the items. |
87 * @private | 85 * @private |
88 */ | 86 */ |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 getItemTop: function(index) { | 199 getItemTop: function(index) { |
202 return Math.floor(index / this.columns) * this.getDefaultItemHeight_(); | 200 return Math.floor(index / this.columns) * this.getDefaultItemHeight_(); |
203 }, | 201 }, |
204 | 202 |
205 /** | 203 /** |
206 * @param {number} index The index of the item. | 204 * @param {number} index The index of the item. |
207 * @return {number} The row of the item. May vary in the case | 205 * @return {number} The row of the item. May vary in the case |
208 * of multiple columns. | 206 * of multiple columns. |
209 * @override | 207 * @override |
210 */ | 208 */ |
211 getItemRow: function(index) { | 209 getItemRow: function(index) { return Math.floor(index / this.columns); }, |
212 return Math.floor(index / this.columns); | |
213 }, | |
214 | 210 |
215 /** | 211 /** |
216 * @param {number} row The row. | 212 * @param {number} row The row. |
217 * @return {number} The index of the first item in the row. | 213 * @return {number} The index of the first item in the row. |
218 * @override | 214 * @override |
219 */ | 215 */ |
220 getFirstItemInRow: function(row) { | 216 getFirstItemInRow: function(row) { return row * this.columns; }, |
221 return row * this.columns; | |
222 }, | |
223 | 217 |
224 /** | 218 /** |
225 * Creates the selection controller to use internally. | 219 * Creates the selection controller to use internally. |
226 * @param {cr.ui.ListSelectionModel} sm The underlying selection model. | 220 * @param {cr.ui.ListSelectionModel} sm The underlying selection model. |
227 * @return {!cr.ui.ListSelectionController} The newly created selection | 221 * @return {!cr.ui.ListSelectionController} The newly created selection |
228 * controller. | 222 * controller. |
229 * @override | 223 * @override |
230 */ | 224 */ |
231 createSelectionController: function(sm) { | 225 createSelectionController: function(sm) { |
232 return new GridSelectionController(sm, this); | 226 return new GridSelectionController(sm, this); |
233 }, | 227 }, |
234 | 228 |
235 /** | 229 /** |
236 * Calculates the number of items fitting in the given viewport. | 230 * Calculates the number of items fitting in the given viewport. |
237 * @param {number} scrollTop The scroll top position. | 231 * @param {number} scrollTop The scroll top position. |
238 * @param {number} clientHeight The height of viewport. | 232 * @param {number} clientHeight The height of viewport. |
239 * @return {{first: number, length: number, last: number}} The index of | 233 * @return {{first: number, length: number, last: number}} The index of |
240 * first item in view port, The number of items, The item past the last. | 234 * first item in view port, The number of items, The item past the last. |
241 * @override | 235 * @override |
242 */ | 236 */ |
243 getItemsInViewPort: function(scrollTop, clientHeight) { | 237 getItemsInViewPort: function(scrollTop, clientHeight) { |
244 var itemHeight = this.getDefaultItemHeight_(); | 238 var itemHeight = this.getDefaultItemHeight_(); |
245 var firstIndex = | 239 var firstIndex = |
246 this.autoExpands ? 0 : this.getIndexForListOffset_(scrollTop); | 240 this.autoExpands ? 0 : this.getIndexForListOffset_(scrollTop); |
247 var columns = this.columns; | 241 var columns = this.columns; |
248 var count = this.autoExpands_ ? this.dataModel.length : Math.max( | 242 var count = this.autoExpands_ ? |
249 columns * (Math.ceil(clientHeight / itemHeight) + 1), | 243 this.dataModel.length : |
250 this.countItemsInRange_(firstIndex, scrollTop + clientHeight)); | 244 Math.max( |
| 245 columns * (Math.ceil(clientHeight / itemHeight) + 1), |
| 246 this.countItemsInRange_(firstIndex, scrollTop + clientHeight)); |
251 count = columns * Math.ceil(count / columns); | 247 count = columns * Math.ceil(count / columns); |
252 count = Math.min(count, this.dataModel.length - firstIndex); | 248 count = Math.min(count, this.dataModel.length - firstIndex); |
253 return { | 249 return {first: firstIndex, length: count, last: firstIndex + count - 1}; |
254 first: firstIndex, | |
255 length: count, | |
256 last: firstIndex + count - 1 | |
257 }; | |
258 }, | 250 }, |
259 | 251 |
260 /** | 252 /** |
261 * Merges list items. Calls the base class implementation and then | 253 * Merges list items. Calls the base class implementation and then |
262 * puts spacers on the right places. | 254 * puts spacers on the right places. |
263 * @param {number} firstIndex The index of first item, inclusively. | 255 * @param {number} firstIndex The index of first item, inclusively. |
264 * @param {number} lastIndex The index of last item, exclusively. | 256 * @param {number} lastIndex The index of last item, exclusively. |
265 * @override | 257 * @override |
266 */ | 258 */ |
267 mergeItems: function(firstIndex, lastIndex) { | 259 mergeItems: function(firstIndex, lastIndex) { |
(...skipping 26 matching lines...) Expand all Loading... |
294 spacer.className = 'spacer'; | 286 spacer.className = 'spacer'; |
295 this.insertBefore(spacer, next); | 287 this.insertBefore(spacer, next); |
296 item = next; | 288 item = next; |
297 } | 289 } |
298 } else | 290 } else |
299 item = next; | 291 item = next; |
300 } | 292 } |
301 | 293 |
302 function isSpacer(child) { | 294 function isSpacer(child) { |
303 return child.classList.contains('spacer') && | 295 return child.classList.contains('spacer') && |
304 child != afterFiller; // Must not be removed. | 296 child != afterFiller; // Must not be removed. |
305 } | 297 } |
306 }, | 298 }, |
307 | 299 |
308 /** | 300 /** |
309 * Returns the height of after filler in the list. | 301 * Returns the height of after filler in the list. |
310 * @param {number} lastIndex The index of item past the last in viewport. | 302 * @param {number} lastIndex The index of item past the last in viewport. |
311 * @return {number} The height of after filler. | 303 * @return {number} The height of after filler. |
312 * @override | 304 * @override |
313 */ | 305 */ |
314 getAfterFillerHeight: function(lastIndex) { | 306 getAfterFillerHeight: function(lastIndex) { |
315 var columns = this.columns; | 307 var columns = this.columns; |
316 var itemHeight = this.getDefaultItemHeight_(); | 308 var itemHeight = this.getDefaultItemHeight_(); |
317 // We calculate the row of last item, and the row of last shown item. | 309 // We calculate the row of last item, and the row of last shown item. |
318 // The difference is the number of rows not shown. | 310 // The difference is the number of rows not shown. |
319 var afterRows = Math.floor((this.dataModel.length - 1) / columns) - | 311 var afterRows = Math.floor((this.dataModel.length - 1) / columns) - |
320 Math.floor((lastIndex - 1) / columns); | 312 Math.floor((lastIndex - 1) / columns); |
321 return afterRows * itemHeight; | 313 return afterRows * itemHeight; |
322 }, | 314 }, |
323 | 315 |
324 /** | 316 /** |
325 * Returns true if the child is a list item. | 317 * Returns true if the child is a list item. |
326 * @param {Node} child Child of the list. | 318 * @param {Node} child Child of the list. |
327 * @return {boolean} True if a list item. | 319 * @return {boolean} True if a list item. |
328 */ | 320 */ |
329 isItem: function(child) { | 321 isItem: function(child) { |
330 // Non-items are before-, afterFiller and spacers added in mergeItems. | 322 // Non-items are before-, afterFiller and spacers added in mergeItems. |
331 return child.nodeType == Node.ELEMENT_NODE && | 323 return child.nodeType == Node.ELEMENT_NODE && |
332 !child.classList.contains('spacer'); | 324 !child.classList.contains('spacer'); |
333 }, | 325 }, |
334 | 326 |
335 redraw: function() { | 327 redraw: function() { |
336 this.updateMetrics_(); | 328 this.updateMetrics_(); |
337 var itemCount = this.dataModel ? this.dataModel.length : 0; | 329 var itemCount = this.dataModel ? this.dataModel.length : 0; |
338 if (this.lastItemCount_ != itemCount) { | 330 if (this.lastItemCount_ != itemCount) { |
339 this.lastItemCount_ = itemCount; | 331 this.lastItemCount_ = itemCount; |
340 // Force recalculation. | 332 // Force recalculation. |
341 this.columns_ = 0; | 333 this.columns_ = 0; |
342 } | 334 } |
(...skipping 21 matching lines...) Expand all Loading... |
364 /** | 356 /** |
365 * Check if accessibility is enabled: if ChromeVox is running | 357 * Check if accessibility is enabled: if ChromeVox is running |
366 * (which provides spoken feedback for accessibility), make up/down | 358 * (which provides spoken feedback for accessibility), make up/down |
367 * behave the same as left/right. That's because the 2-dimensional | 359 * behave the same as left/right. That's because the 2-dimensional |
368 * structure of the grid isn't exposed, so it makes more sense to a | 360 * structure of the grid isn't exposed, so it makes more sense to a |
369 * user who is relying on spoken feedback to flatten it. | 361 * user who is relying on spoken feedback to flatten it. |
370 * @return {boolean} True if accessibility is enabled. | 362 * @return {boolean} True if accessibility is enabled. |
371 */ | 363 */ |
372 isAccessibilityEnabled: function() { | 364 isAccessibilityEnabled: function() { |
373 return window.cvox && window.cvox.Api && | 365 return window.cvox && window.cvox.Api && |
374 window.cvox.Api.isChromeVoxActive && | 366 window.cvox.Api.isChromeVoxActive && |
375 window.cvox.Api.isChromeVoxActive(); | 367 window.cvox.Api.isChromeVoxActive(); |
376 }, | 368 }, |
377 | 369 |
378 /** | 370 /** |
379 * Returns the index below (y axis) the given element. | 371 * Returns the index below (y axis) the given element. |
380 * @param {number} index The index to get the index below. | 372 * @param {number} index The index to get the index below. |
381 * @return {number} The index below or -1 if not found. | 373 * @return {number} The index below or -1 if not found. |
382 * @override | 374 * @override |
383 */ | 375 */ |
384 getIndexBelow: function(index) { | 376 getIndexBelow: function(index) { |
385 if (this.isAccessibilityEnabled()) | 377 if (this.isAccessibilityEnabled()) |
(...skipping 19 matching lines...) Expand all Loading... |
405 index -= this.grid_.columns; | 397 index -= this.grid_.columns; |
406 return Math.max(index, 0); | 398 return Math.max(index, 0); |
407 }, | 399 }, |
408 | 400 |
409 /** | 401 /** |
410 * Returns the index before (x axis) the given element. | 402 * Returns the index before (x axis) the given element. |
411 * @param {number} index The index to get the index before. | 403 * @param {number} index The index to get the index before. |
412 * @return {number} The index before or -1 if not found. | 404 * @return {number} The index before or -1 if not found. |
413 * @override | 405 * @override |
414 */ | 406 */ |
415 getIndexBefore: function(index) { | 407 getIndexBefore: function(index) { return index - 1; }, |
416 return index - 1; | |
417 }, | |
418 | 408 |
419 /** | 409 /** |
420 * Returns the index after (x axis) the given element. | 410 * Returns the index after (x axis) the given element. |
421 * @param {number} index The index to get the index after. | 411 * @param {number} index The index to get the index after. |
422 * @return {number} The index after or -1 if not found. | 412 * @return {number} The index after or -1 if not found. |
423 * @override | 413 * @override |
424 */ | 414 */ |
425 getIndexAfter: function(index) { | 415 getIndexAfter: function(index) { |
426 if (index == this.getLastIndex()) { | 416 if (index == this.getLastIndex()) { |
427 return -1; | 417 return -1; |
428 } | 418 } |
429 return index + 1; | 419 return index + 1; |
430 } | 420 } |
431 }; | 421 }; |
432 | 422 |
433 return { | 423 return { |
434 Grid: Grid, | 424 Grid: Grid, |
435 GridItem: GridItem, | 425 GridItem: GridItem, |
436 GridSelectionController: GridSelectionController | 426 GridSelectionController: GridSelectionController |
437 }; | 427 }; |
438 }); | 428 }); |
OLD | NEW |