| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * PreviewPanel UI class. | 8 * PreviewPanel UI class. |
| 9 * @param {HTMLElement} element DOM Element of preview panel. | 9 * @param {HTMLElement} element DOM Element of preview panel. |
| 10 * @param {PreviewPanel.VisibilityType} visibilityType Initial value of the | 10 * @param {PreviewPanel.VisibilityType} visibilityType Initial value of the |
| 11 * visibility type. | 11 * visibility type. |
| 12 * @param {string} currentPath Initial value of the current path. | 12 * @param {string} currentPath Initial value of the current path. |
| 13 * @param {MetadataCache} metadataCache Metadata cache. |
| 13 * @constructor | 14 * @constructor |
| 14 * @extends {cr.EventTarget} | 15 * @extends {cr.EventTarget} |
| 15 */ | 16 */ |
| 16 var PreviewPanel = function(element, visibilityType, currentPath) { | 17 var PreviewPanel = function(element, |
| 18 visibilityType, |
| 19 currentPath, |
| 20 metadataCache) { |
| 17 /** | 21 /** |
| 18 * The cached height of preview panel. | 22 * The cached height of preview panel. |
| 19 * @type {number} | 23 * @type {number} |
| 20 * @private | 24 * @private |
| 21 */ | 25 */ |
| 22 this.height_ = 0; | 26 this.height_ = 0; |
| 23 | 27 |
| 24 /** | 28 /** |
| 25 * Visiblity type of the preview panel. | 29 * Visiblity type of the preview panel. |
| 26 * @type {PreviewPanel.VisiblityType} | 30 * @type {PreviewPanel.VisiblityType} |
| 27 * @private | 31 * @private |
| 28 */ | 32 */ |
| 29 this.visibilityType_ = visibilityType; | 33 this.visibilityType_ = visibilityType; |
| 30 | 34 |
| 31 /** | 35 /** |
| 32 * Current path to be desplayed. | 36 * Current path to be desplayed. |
| 33 * @type {string} | 37 * @type {string} |
| 34 * @private | 38 * @private |
| 35 */ | 39 */ |
| 36 this.currentPath_ = currentPath || '/'; | 40 this.currentPath_ = currentPath || '/'; |
| 37 | 41 |
| 38 /** | 42 /** |
| 39 * Dom element of the preview panel. | 43 * Dom element of the preview panel. |
| 40 * @type {HTMLElement} | 44 * @type {HTMLElement} |
| 41 * @private | 45 * @private |
| 42 */ | 46 */ |
| 43 this.element_ = element; | 47 this.element_ = element; |
| 44 | 48 |
| 45 /** | 49 /** |
| 46 * @type {HTMLElement} | 50 * @type {PreviewPanel.Thumbnails} |
| 47 * @private | |
| 48 */ | 51 */ |
| 49 this.thumbnailElement_ = element.querySelector('.preview-thumbnails'); | 52 this.thumbnails = new PreviewPanel.Thumbnails( |
| 53 element.querySelector('.preview-thumbnails'), metadataCache); |
| 50 | 54 |
| 51 /** | 55 /** |
| 52 * @type {HTMLElement} | 56 * @type {HTMLElement} |
| 53 * @private | 57 * @private |
| 54 */ | 58 */ |
| 55 this.summaryElement_ = element.querySelector('.preview-summary'); | 59 this.summaryElement_ = element.querySelector('.preview-summary'); |
| 56 | 60 |
| 57 /** | 61 /** |
| 58 * @type {PreviewPanel.CalculatingSizeLabel} | 62 * @type {PreviewPanel.CalculatingSizeLabel} |
| 59 * @private | 63 * @private |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 * @private | 326 * @private |
| 323 */ | 327 */ |
| 324 PreviewPanel.CalculatingSizeLabel.prototype.onStep_ = function() { | 328 PreviewPanel.CalculatingSizeLabel.prototype.onStep_ = function() { |
| 325 var text = str('CALCULATING_SIZE'); | 329 var text = str('CALCULATING_SIZE'); |
| 326 for (var i = 0; i < ~~(this.count_ / 2) % 4; i++) { | 330 for (var i = 0; i < ~~(this.count_ / 2) % 4; i++) { |
| 327 text += '.'; | 331 text += '.'; |
| 328 } | 332 } |
| 329 this.element_.textContent = text; | 333 this.element_.textContent = text; |
| 330 this.count_++; | 334 this.count_++; |
| 331 }; | 335 }; |
| 336 |
| 337 /** |
| 338 * Thumbnails on the preview panel. |
| 339 * |
| 340 * @param {HTMLElement} element DOM Element of thumbnail container. |
| 341 * @param {MetadataCache} metadataCache MetadataCache. |
| 342 * @constructor |
| 343 */ |
| 344 PreviewPanel.Thumbnails = function(element, metadataCache) { |
| 345 this.element_ = element; |
| 346 this.metadataCache_ = metadataCache; |
| 347 this.sequence_ = 0; |
| 348 Object.seal(this); |
| 349 }; |
| 350 |
| 351 /** |
| 352 * Maximium number of thumbnails. |
| 353 * @const {number} |
| 354 */ |
| 355 PreviewPanel.Thumbnails.MAX_THUMBNAIL_COUNT = 4; |
| 356 |
| 357 /** |
| 358 * Edge length of the thumbnail square. |
| 359 * @const {number} |
| 360 */ |
| 361 PreviewPanel.Thumbnails.THUMBNAIL_SIZE = 35; |
| 362 |
| 363 /** |
| 364 * Longer edge length of zoomed thumbnail rectangle. |
| 365 * @const {number} |
| 366 */ |
| 367 PreviewPanel.Thumbnails.ZOOMED_THUMBNAIL_SIZE = 200; |
| 368 |
| 369 PreviewPanel.Thumbnails.prototype = { |
| 370 /** |
| 371 * Sets entries to be displayed in the view. |
| 372 * @param {Array.<Entry>} value Entries. |
| 373 */ |
| 374 set selection(value) { |
| 375 this.sequence_++; |
| 376 this.loadThumbnails_(value); |
| 377 } |
| 378 }; |
| 379 |
| 380 /** |
| 381 * Loads thumbnail images. |
| 382 * @param {FileSelection} selection Selection containing entries that are |
| 383 * sources of images. |
| 384 * @private |
| 385 */ |
| 386 PreviewPanel.Thumbnails.prototype.loadThumbnails_ = function(selection) { |
| 387 var entries = selection.entries; |
| 388 this.element_.classList.remove('has-zoom'); |
| 389 this.element_.innerText = ''; |
| 390 var clickHandler = selection.tasks && |
| 391 selection.tasks.executeDefault.bind(selection.tasks); |
| 392 var length = Math.min(entries.length, |
| 393 PreviewPanel.Thumbnails.MAX_THUMBNAIL_COUNT); |
| 394 for (var i = 0; i < length; i++) { |
| 395 // Create a box. |
| 396 var box = this.element_.ownerDocument.createElement('div'); |
| 397 box.style.zIndex = PreviewPanel.Thumbnails.MAX_THUMBNAIL_COUNT + 1 - i; |
| 398 |
| 399 // Load the image. |
| 400 FileGrid.decorateThumbnailBox(box, |
| 401 entries[i], |
| 402 this.metadataCache_, |
| 403 ThumbnailLoader.FillMode.FILL, |
| 404 FileGrid.ThumbnailQuality.LOW, |
| 405 i == 0 && length == 1 && |
| 406 this.setZoomedImage_.bind(this)); |
| 407 |
| 408 // Register the click handler. |
| 409 if (clickHandler) |
| 410 box.addEventListener('click', clickHandler); |
| 411 |
| 412 // Append |
| 413 this.element_.appendChild(box); |
| 414 } |
| 415 }; |
| 416 |
| 417 /** |
| 418 * Create the zoomed version of image and set it to the DOM element to show the |
| 419 * zoomed image. |
| 420 * |
| 421 * @param {Image} image Image to be source of the zoomed image. |
| 422 * @param {transform} transform Transoformation to be applied to the image. |
| 423 * @private |
| 424 */ |
| 425 PreviewPanel.Thumbnails.prototype.setZoomedImage_ = |
| 426 function(image, transform) { |
| 427 if (!image) |
| 428 return; |
| 429 var width = image.width || 0; |
| 430 var height = image.height || 0; |
| 431 if (width == 0 || |
| 432 height == 0 || |
| 433 (width < PreviewPanel.Thumbnails.THUMBNAIL_SIZE * 2 && |
| 434 height < PreviewPanel.Thumbnails.THUMBNAIL_SIZE * 2)) |
| 435 return; |
| 436 |
| 437 var scale = Math.min(1, |
| 438 PreviewPanel.Thumbnails.ZOOMED_THUMBNAIL_SIZE / |
| 439 Math.max(width, height)); |
| 440 var imageWidth = ~~(width * scale); |
| 441 var imageHeight = ~~(height * scale); |
| 442 var zoomedImage = this.element_.ownerDocument.createElement('img'); |
| 443 |
| 444 if (scale < 0.3) { |
| 445 // Scaling large images kills animation. Downscale it in advance. |
| 446 // Canvas scales images with liner interpolation. Make a larger |
| 447 // image (but small enough to not kill animation) and let IMAGE |
| 448 // scale it smoothly. |
| 449 var INTERMEDIATE_SCALE = 3; |
| 450 var canvas = this.element_.ownerDocument.createElement('canvas'); |
| 451 canvas.width = imageWidth * INTERMEDIATE_SCALE; |
| 452 canvas.height = imageHeight * INTERMEDIATE_SCALE; |
| 453 var ctx = canvas.getContext('2d'); |
| 454 ctx.drawImage(image, 0, 0, canvas.width, canvas.height); |
| 455 // Using bigger than default compression reduces image size by |
| 456 // several times. Quality degradation compensated by greater resolution. |
| 457 zoomedImage.src = canvas.toDataURL('image/jpeg', 0.6); |
| 458 } else { |
| 459 zoomedImage.src = image.src; |
| 460 } |
| 461 |
| 462 var boxWidth = Math.max(PreviewPanel.Thumbnails.THUMBNAIL_SIZE, imageWidth); |
| 463 var boxHeight = Math.max(PreviewPanel.Thumbnails.THUMBNAIL_SIZE, imageHeight); |
| 464 if (transform && transform.rotate90 % 2 == 1) { |
| 465 var t = boxWidth; |
| 466 boxWidth = boxHeight; |
| 467 boxHeight = t; |
| 468 } |
| 469 |
| 470 util.applyTransform(zoomedImage, transform); |
| 471 |
| 472 var zoomedBox = this.element_.ownerDocument.createElement('div'); |
| 473 zoomedBox.className = 'popup'; |
| 474 zoomedBox.style.width = boxWidth + 'px'; |
| 475 zoomedBox.style.height = boxHeight + 'px'; |
| 476 zoomedBox.appendChild(zoomedImage); |
| 477 |
| 478 this.element_.appendChild(zoomedBox); |
| 479 this.element_.classList.add('has-zoom'); |
| 480 return; |
| 481 }; |
| OLD | NEW |