| 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 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The current selection object. | 8 * The current selection object. |
| 9 * | 9 * |
| 10 * @param {FileManager} fileManager FileManager instance. | 10 * @param {FileManager} fileManager FileManager instance. |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 return; | 317 return; |
| 318 selection.tasks.display(this.taskItems_); | 318 selection.tasks.display(this.taskItems_); |
| 319 selection.tasks.updateMenuItem(); | 319 selection.tasks.updateMenuItem(); |
| 320 }.bind(this)); | 320 }.bind(this)); |
| 321 } else { | 321 } else { |
| 322 this.taskItems_.hidden = true; | 322 this.taskItems_.hidden = true; |
| 323 } | 323 } |
| 324 | 324 |
| 325 // Update preview panels. | 325 // Update preview panels. |
| 326 var wasVisible = this.previewPanel_.visible; | 326 var wasVisible = this.previewPanel_.visible; |
| 327 var thumbnailEntries; | 327 var thumbnailSelection; |
| 328 if (selection.totalCount == 0) { | 328 if (selection.totalCount != 0) { |
| 329 thumbnailEntries = [ | 329 thumbnailSelection = selection; |
| 330 this.fileManager_.getCurrentDirectoryEntry() | |
| 331 ]; | |
| 332 } else { | 330 } else { |
| 333 thumbnailEntries = selection.entries; | 331 thumbnailSelection = { |
| 332 entries: [this.fileManager_.getCurrentDirectoryEntry()] |
| 333 }; |
| 334 } | 334 } |
| 335 this.previewPanel_.setSelection(selection); | 335 this.previewPanel_.setSelection(selection); |
| 336 this.showPreviewThumbnails_(thumbnailEntries); | 336 this.previewPanel_.thumbnails.selection = thumbnailSelection; |
| 337 | 337 |
| 338 // Update breadcrums. | 338 // Update breadcrums. |
| 339 var updateTarget = null; | 339 var updateTarget = null; |
| 340 var path = this.fileManager_.getCurrentDirectory(); | 340 var path = this.fileManager_.getCurrentDirectory(); |
| 341 if (selection.totalCount == 1) { | 341 if (selection.totalCount == 1) { |
| 342 // Shows the breadcrumb list when a file is selected. | 342 // Shows the breadcrumb list when a file is selected. |
| 343 updateTarget = selection.entries[0].fullPath; | 343 updateTarget = selection.entries[0].fullPath; |
| 344 } else if (selection.totalCount == 0 && | 344 } else if (selection.totalCount == 0 && |
| 345 this.previewPanel_.visible) { | 345 this.previewPanel_.visible) { |
| 346 // Shows the breadcrumb list when no file is selected and the preview | 346 // Shows the breadcrumb list when no file is selected and the preview |
| (...skipping 15 matching lines...) Expand all Loading... |
| 362 // Update context menu. | 362 // Update context menu. |
| 363 this.fileManager_.updateContextMenuActionItems(null, false); | 363 this.fileManager_.updateContextMenuActionItems(null, false); |
| 364 | 364 |
| 365 // Inform tests it's OK to click buttons now. | 365 // Inform tests it's OK to click buttons now. |
| 366 if (selection.totalCount > 0) { | 366 if (selection.totalCount > 0) { |
| 367 chrome.test.sendMessage('selection-change-complete'); | 367 chrome.test.sendMessage('selection-change-complete'); |
| 368 } | 368 } |
| 369 }; | 369 }; |
| 370 | 370 |
| 371 /** | 371 /** |
| 372 * Renders preview thumbnails in preview panel. | |
| 373 * | |
| 374 * @param {Array.<FileEntry>} entries The entries of selected object. | |
| 375 * @private | |
| 376 */ | |
| 377 FileSelectionHandler.prototype.showPreviewThumbnails_ = function(entries) { | |
| 378 var selection = this.selection; | |
| 379 var thumbnails = []; | |
| 380 var thumbnailCount = 0; | |
| 381 var thumbnailLoaded = -1; | |
| 382 var forcedShowTimeout = null; | |
| 383 var thumbnailsHaveZoom = false; | |
| 384 var self = this; | |
| 385 | |
| 386 var showThumbnails = function() { | |
| 387 // have-zoom class may be updated twice: then timeout exceeds and then | |
| 388 // then all images loaded. | |
| 389 if (self.selection == selection) { | |
| 390 if (thumbnailsHaveZoom) { | |
| 391 self.previewThumbnails_.classList.add('has-zoom'); | |
| 392 } else { | |
| 393 self.previewThumbnails_.classList.remove('has-zoom'); | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 if (forcedShowTimeout === null) | |
| 398 return; | |
| 399 clearTimeout(forcedShowTimeout); | |
| 400 forcedShowTimeout = null; | |
| 401 | |
| 402 // FileSelection could change while images are loading. | |
| 403 if (self.selection == selection) { | |
| 404 self.previewThumbnails_.textContent = ''; | |
| 405 for (var i = 0; i < thumbnails.length; i++) | |
| 406 self.previewThumbnails_.appendChild(thumbnails[i]); | |
| 407 } | |
| 408 }; | |
| 409 | |
| 410 var onThumbnailLoaded = function() { | |
| 411 thumbnailLoaded++; | |
| 412 if (thumbnailLoaded == thumbnailCount) | |
| 413 showThumbnails(); | |
| 414 }; | |
| 415 | |
| 416 var thumbnailClickHandler = function() { | |
| 417 if (selection.tasks) | |
| 418 selection.tasks.executeDefault(); | |
| 419 }; | |
| 420 | |
| 421 var doc = this.fileManager_.document_; | |
| 422 for (var i = 0; i < entries.length; i++) { | |
| 423 var entry = entries[i]; | |
| 424 | |
| 425 if (thumbnailCount < FileSelectionHandler.MAX_PREVIEW_THUMBNAIL_COUNT) { | |
| 426 var box = doc.createElement('div'); | |
| 427 box.className = 'thumbnail'; | |
| 428 if (thumbnailCount == 0) { | |
| 429 var zoomed = doc.createElement('div'); | |
| 430 zoomed.hidden = true; | |
| 431 thumbnails.push(zoomed); | |
| 432 var onFirstThumbnailLoaded = function(img, transform) { | |
| 433 if (img && self.decorateThumbnailZoom_(zoomed, img, transform)) { | |
| 434 zoomed.hidden = false; | |
| 435 thumbnailsHaveZoom = true; | |
| 436 } | |
| 437 onThumbnailLoaded(); | |
| 438 }; | |
| 439 var thumbnail = this.renderThumbnail_(entry, onFirstThumbnailLoaded); | |
| 440 zoomed.addEventListener('click', thumbnailClickHandler); | |
| 441 } else { | |
| 442 var thumbnail = this.renderThumbnail_(entry, onThumbnailLoaded); | |
| 443 } | |
| 444 thumbnailCount++; | |
| 445 box.appendChild(thumbnail); | |
| 446 box.style.zIndex = | |
| 447 FileSelectionHandler.MAX_PREVIEW_THUMBNAIL_COUNT + 1 - i; | |
| 448 box.addEventListener('click', thumbnailClickHandler); | |
| 449 | |
| 450 thumbnails.push(box); | |
| 451 } | |
| 452 } | |
| 453 | |
| 454 forcedShowTimeout = setTimeout(showThumbnails, | |
| 455 FileManager.THUMBNAIL_SHOW_DELAY); | |
| 456 onThumbnailLoaded(); | |
| 457 }; | |
| 458 | |
| 459 /** | |
| 460 * Renders a thumbnail for the buttom panel. | |
| 461 * | |
| 462 * @param {Entry} entry Entry to render for. | |
| 463 * @param {function} callback Called when image loaded. | |
| 464 * @return {HTMLDivElement} Created element. | |
| 465 * @private | |
| 466 */ | |
| 467 FileSelectionHandler.prototype.renderThumbnail_ = function(entry, callback) { | |
| 468 var thumbnail = this.fileManager_.document_.createElement('div'); | |
| 469 FileGrid.decorateThumbnailBox(thumbnail, | |
| 470 entry, | |
| 471 this.fileManager_.metadataCache_, | |
| 472 ThumbnailLoader.FillMode.FILL, | |
| 473 FileGrid.ThumbnailQuality.LOW, | |
| 474 callback); | |
| 475 return thumbnail; | |
| 476 }; | |
| 477 | |
| 478 /** | |
| 479 * Updates the breadcrumbs in the preview panel. | 372 * Updates the breadcrumbs in the preview panel. |
| 480 * | 373 * |
| 481 * @param {?string} path Path to be shown in the breadcrumbs list | 374 * @param {?string} path Path to be shown in the breadcrumbs list |
| 482 * @private | 375 * @private |
| 483 */ | 376 */ |
| 484 FileSelectionHandler.prototype.updatePreviewPanelBreadcrumbs_ = function(path) { | 377 FileSelectionHandler.prototype.updatePreviewPanelBreadcrumbs_ = function(path) { |
| 485 if (!path) | 378 if (!path) |
| 486 this.searchBreadcrumbs_.hide(); | 379 this.searchBreadcrumbs_.hide(); |
| 487 else | 380 else |
| 488 this.searchBreadcrumbs_.show(PathUtil.getRootPath(path), path); | 381 this.searchBreadcrumbs_.show(PathUtil.getRootPath(path), path); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 501 this.searchBreadcrumbs_.hide(); | 394 this.searchBreadcrumbs_.hide(); |
| 502 return; | 395 return; |
| 503 } | 396 } |
| 504 | 397 |
| 505 var entry = this.fileManager_.getFileList().item( | 398 var entry = this.fileManager_.getFileList().item( |
| 506 selectedIndexes[0]); | 399 selectedIndexes[0]); |
| 507 this.searchBreadcrumbs_.show( | 400 this.searchBreadcrumbs_.show( |
| 508 PathUtil.getRootPath(entry.fullPath), | 401 PathUtil.getRootPath(entry.fullPath), |
| 509 entry.fullPath); | 402 entry.fullPath); |
| 510 }; | 403 }; |
| 511 | |
| 512 /** | |
| 513 * Creates enlarged image for a bottom pannel thumbnail. | |
| 514 * Image's assumed to be just loaded and not inserted into the DOM. | |
| 515 * | |
| 516 * @param {HTMLElement} largeImageBox DIV element to decorate. | |
| 517 * @param {HTMLElement} img Loaded image. | |
| 518 * @param {Object} transform Image transformation description. | |
| 519 * @return {boolean} True if zoomed image is present. | |
| 520 * @private | |
| 521 */ | |
| 522 FileSelectionHandler.prototype.decorateThumbnailZoom_ = function( | |
| 523 largeImageBox, img, transform) { | |
| 524 var width = img.width; | |
| 525 var height = img.height; | |
| 526 var THUMBNAIL_SIZE = 35; | |
| 527 if (width < THUMBNAIL_SIZE * 2 && height < THUMBNAIL_SIZE * 2) | |
| 528 return false; | |
| 529 | |
| 530 var scale = Math.min(1, | |
| 531 FileSelectionHandler.IMAGE_HOVER_PREVIEW_SIZE / Math.max(width, height)); | |
| 532 | |
| 533 var imageWidth = Math.round(width * scale); | |
| 534 var imageHeight = Math.round(height * scale); | |
| 535 | |
| 536 var largeImage = this.fileManager_.document_.createElement('img'); | |
| 537 if (scale < 0.3) { | |
| 538 // Scaling large images kills animation. Downscale it in advance. | |
| 539 | |
| 540 // Canvas scales images with liner interpolation. Make a larger | |
| 541 // image (but small enough to not kill animation) and let IMG | |
| 542 // scale it smoothly. | |
| 543 var INTERMEDIATE_SCALE = 3; | |
| 544 var canvas = this.fileManager_.document_.createElement('canvas'); | |
| 545 canvas.width = imageWidth * INTERMEDIATE_SCALE; | |
| 546 canvas.height = imageHeight * INTERMEDIATE_SCALE; | |
| 547 var ctx = canvas.getContext('2d'); | |
| 548 ctx.drawImage(img, 0, 0, canvas.width, canvas.height); | |
| 549 // Using bigger than default compression reduces image size by | |
| 550 // several times. Quality degradation compensated by greater resolution. | |
| 551 largeImage.src = canvas.toDataURL('image/jpeg', 0.6); | |
| 552 } else { | |
| 553 largeImage.src = img.src; | |
| 554 } | |
| 555 largeImageBox.className = 'popup'; | |
| 556 | |
| 557 var boxWidth = Math.max(THUMBNAIL_SIZE, imageWidth); | |
| 558 var boxHeight = Math.max(THUMBNAIL_SIZE, imageHeight); | |
| 559 | |
| 560 if (transform && transform.rotate90 % 2 == 1) { | |
| 561 var t = boxWidth; | |
| 562 boxWidth = boxHeight; | |
| 563 boxHeight = t; | |
| 564 } | |
| 565 | |
| 566 var style = largeImageBox.style; | |
| 567 style.width = boxWidth + 'px'; | |
| 568 style.height = boxHeight + 'px'; | |
| 569 style.top = (-boxHeight + THUMBNAIL_SIZE) + 'px'; | |
| 570 | |
| 571 var style = largeImage.style; | |
| 572 style.width = imageWidth + 'px'; | |
| 573 style.height = imageHeight + 'px'; | |
| 574 style.left = (boxWidth - imageWidth) / 2 + 'px'; | |
| 575 style.top = (boxHeight - imageHeight) / 2 + 'px'; | |
| 576 style.position = 'relative'; | |
| 577 | |
| 578 util.applyTransform(largeImage, transform); | |
| 579 | |
| 580 largeImageBox.appendChild(largeImage); | |
| 581 largeImageBox.style.zIndex = 1000; | |
| 582 return true; | |
| 583 }; | |
| OLD | NEW |