| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 /* | 5 /* |
| 6 * Base class that Ribbon uses to display photos. | 6 * Base class that Ribbon uses to display photos. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 function RibbonClient() {} | 9 function RibbonClient() {} |
| 10 | 10 |
| (...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 this.selectedIndex_ = -1; | 494 this.selectedIndex_ = -1; |
| 495 | 495 |
| 496 this.arrowLeft_ = arrowLeft; | 496 this.arrowLeft_ = arrowLeft; |
| 497 this.arrowLeft_. | 497 this.arrowLeft_. |
| 498 addEventListener('click', this.selectNext.bind(this, -1, null)); | 498 addEventListener('click', this.selectNext.bind(this, -1, null)); |
| 499 | 499 |
| 500 this.arrowRight_ = arrowRight; | 500 this.arrowRight_ = arrowRight; |
| 501 this.arrowRight_. | 501 this.arrowRight_. |
| 502 addEventListener('click', this.selectNext.bind(this, 1, null)); | 502 addEventListener('click', this.selectNext.bind(this, 1, null)); |
| 503 | 503 |
| 504 this.fadeLeft_ = this.document_.createElement('div'); | 504 this.bar_ = this.document_.createElement('div'); |
| 505 this.fadeLeft_.className = 'fade left'; | 505 this.bar_.className = 'ribbon'; |
| 506 this.container_.appendChild(this.fadeLeft_); | 506 this.container_.appendChild(this.bar_); |
| 507 | |
| 508 this.bars_ = []; | |
| 509 for (var i = 0; i < 2; i++) { | |
| 510 var bar = this.document_.createElement('div'); | |
| 511 bar.className = 'ribbon'; | |
| 512 this.container_.appendChild(bar); | |
| 513 this.bars_.push(bar); | |
| 514 } | |
| 515 this.activeBarIndex_ = 0; | |
| 516 ImageUtil.setAttribute(this.bars_[0], 'inactive', false); | |
| 517 ImageUtil.setAttribute(this.bars_[1], 'inactive', true); | |
| 518 | |
| 519 this.fadeRight_ = this.document_.createElement('div'); | |
| 520 this.fadeRight_.className = 'fade right'; | |
| 521 this.container_.appendChild(this.fadeRight_); | |
| 522 } | 507 } |
| 523 | 508 |
| 524 Ribbon.PAGING_SINGLE_ITEM_DELAY = 20; | 509 Ribbon.PAGING_SINGLE_ITEM_DELAY = 20; |
| 525 Ribbon.PAGING_ANIMATION_DURATION = 200; | 510 Ribbon.PAGING_ANIMATION_DURATION = 200; |
| 526 | 511 |
| 527 Ribbon.prototype.getSelectedItem = function () { | 512 Ribbon.prototype.getSelectedItem = function () { |
| 528 return this.items_[this.selectedIndex_]; | 513 return this.items_[this.selectedIndex_]; |
| 529 }; | 514 }; |
| 530 | 515 |
| 531 Ribbon.prototype.clear = function() { | 516 Ribbon.prototype.clear = function() { |
| 532 this.bars_[0].textContent = ''; | 517 this.bar_.textContent = ''; |
| 533 this.bars_[1].textContent = ''; | |
| 534 this.activeBarIndex_ = 0; | |
| 535 ImageUtil.setAttribute(this.bars_[0], 'inactive', false); | |
| 536 ImageUtil.setAttribute(this.bars_[1], 'inactive', true); | |
| 537 this.items_ = []; | 518 this.items_ = []; |
| 538 this.selectedIndex_ = -1; | 519 this.selectedIndex_ = -1; |
| 539 this.firstVisibleIndex_ = 0; | 520 this.firstVisibleIndex_ = 0; |
| 540 this.lastVisibleIndex_ = -1; // Zero thumbnails | 521 this.lastVisibleIndex_ = -1; // Zero thumbnails |
| 541 this.sequenceDirection_ = 0; | 522 this.sequenceDirection_ = 0; |
| 542 this.sequenceLength_ = 0; | 523 this.sequenceLength_ = 0; |
| 543 }; | 524 }; |
| 544 | 525 |
| 545 Ribbon.prototype.add = function(url) { | 526 Ribbon.prototype.add = function(url) { |
| 546 var index = this.items_.length; | 527 var index = this.items_.length; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 | 613 |
| 633 var selectedItem = this.getSelectedItem(); | 614 var selectedItem = this.getSelectedItem(); |
| 634 var self = this; | 615 var self = this; |
| 635 var item = this.items_[index]; | 616 var item = this.items_[index]; |
| 636 item.fetchMetadata(this.metadataProvider_, function(metadata) { | 617 item.fetchMetadata(this.metadataProvider_, function(metadata) { |
| 637 if (!selectedItem.isSelected()) return; | 618 if (!selectedItem.isSelected()) return; |
| 638 self.client_.prefetchImage(index, item.getContent(), metadata); | 619 self.client_.prefetchImage(index, item.getContent(), metadata); |
| 639 }); | 620 }); |
| 640 }; | 621 }; |
| 641 | 622 |
| 642 Ribbon.prototype.updateControls_ = function() { | 623 Ribbon.ITEMS_COUNT = 5; |
| 643 ImageUtil.setAttribute(this.fadeLeft_, 'active', this.firstVisibleIndex_ > 0); | |
| 644 ImageUtil.setAttribute(this.fadeRight_, 'active', | |
| 645 this.lastVisibleIndex_ + 1 < this.items_.length); | |
| 646 }; | |
| 647 | 624 |
| 648 Ribbon.prototype.redraw = function() { | 625 Ribbon.prototype.redraw = function() { |
| 649 // The thumbnails are square. | 626 // TODO(dgozman): use margin instead of 2 here. |
| 650 var itemWidth = this.bars_[0].parentNode.clientHeight; | 627 var itemWidth = this.bar_.clientHeight - 2; |
| 651 var width = this.bars_[0].parentNode.clientWidth; | 628 var fullItems = Ribbon.ITEMS_COUNT; |
| 652 | 629 fullItems = Math.min(fullItems, this.items_.length); |
| 653 var fullItems = Math.floor(width / itemWidth); | 630 var right = Math.floor((fullItems - 1) / 2); |
| 654 | 631 |
| 655 var fullWidth = fullItems * itemWidth; | 632 var fullWidth = fullItems * itemWidth; |
| 633 this.bar_.style.width = fullWidth + 'px'; |
| 656 | 634 |
| 657 this.bars_[0].style.width = fullWidth + 'px'; | 635 var lastIndex = this.selectedIndex_ + right; |
| 658 this.bars_[1].style.width = fullWidth + 'px'; | 636 lastIndex = Math.max(lastIndex, fullItems - 1); |
| 659 | 637 lastIndex = Math.min(lastIndex, this.items_.length - 1); |
| 660 // Position the shadows over the first and the last visible thumbnails. | 638 var firstIndex = lastIndex - fullItems + 1; |
| 661 this.fadeLeft_.style.left = 0; | |
| 662 this.fadeRight_.style.right = (width - fullWidth) + 'px'; | |
| 663 | |
| 664 fullItems = Math.min(fullItems, this.items_.length); | |
| 665 var firstIndex = this.firstVisibleIndex_; | |
| 666 var lastIndex = firstIndex + fullItems - 1; | |
| 667 | |
| 668 if (this.selectedIndex_ <= firstIndex && firstIndex > 0) { | |
| 669 firstIndex = Math.max(0, this.selectedIndex_ - (fullItems >> 1)); | |
| 670 lastIndex = firstIndex + fullItems - 1; | |
| 671 } | |
| 672 | |
| 673 if (this.selectedIndex_ >= lastIndex && lastIndex < this.items_.length - 1) { | |
| 674 lastIndex = Math.min(this.items_.length - 1, | |
| 675 this.selectedIndex_ + (fullItems >> 1)); | |
| 676 firstIndex = lastIndex - fullItems + 1; | |
| 677 } | |
| 678 | |
| 679 this.updateControls_(); | |
| 680 | 639 |
| 681 if (this.firstVisibleIndex_ == firstIndex && | 640 if (this.firstVisibleIndex_ == firstIndex && |
| 682 this.lastVisibleIndex_ == lastIndex) { | 641 this.lastVisibleIndex_ == lastIndex) { |
| 683 return; | 642 return; |
| 684 } | 643 } |
| 685 | 644 |
| 686 var activeBar = this.bars_[this.activeBarIndex_]; | 645 if (this.lastVisibleIndex_ == -1) { |
| 687 var children = activeBar.childNodes; | 646 this.firstVisibleIndex_ = firstIndex; |
| 688 var totalDuration = children.length * Ribbon.PAGING_SINGLE_ITEM_DELAY + | 647 this.lastVisibleIndex_ = lastIndex; |
| 689 Ribbon.PAGING_ANIMATION_DURATION; | |
| 690 | |
| 691 var direction = 1; | |
| 692 var delay = 0; | |
| 693 if (firstIndex < this.firstVisibleIndex_) { | |
| 694 direction = -1; | |
| 695 delay = (children.length - 1) * Ribbon.PAGING_SINGLE_ITEM_DELAY; | |
| 696 } | |
| 697 for (var index = 0; index < children.length; ++index) { | |
| 698 setTimeout( | |
| 699 ImageUtil.setAttribute.bind(null, children[index], 'inactive', true), | |
| 700 delay); | |
| 701 delay += direction * Ribbon.PAGING_SINGLE_ITEM_DELAY; | |
| 702 } | 648 } |
| 703 | 649 |
| 704 // Place inactive bar below active after animation is finished. | 650 this.bar_.textContent = ''; |
| 705 setTimeout( | 651 var startIndex = Math.min(firstIndex, this.firstVisibleIndex_); |
| 706 ImageUtil.setAttribute.bind(null, activeBar, 'inactive', true), | 652 var toRemove = []; |
| 707 totalDuration); | 653 for (var index = startIndex + 1; |
| 654 index <= Math.max(lastIndex, this.lastVisibleIndex_); |
| 655 ++index) { |
| 656 var box = this.items_[index].getBox(0); |
| 657 box.style.marginLeft = '0'; |
| 658 this.bar_.appendChild(box); |
| 659 if (index < firstIndex || index > lastIndex) { |
| 660 toRemove.push(index); |
| 661 } |
| 662 } |
| 663 |
| 664 var margin = itemWidth * Math.abs(firstIndex - this.firstVisibleIndex_); |
| 665 var startBox = this.items_[startIndex].getBox(0); |
| 666 if (startIndex == firstIndex) { |
| 667 startBox.style.marginLeft = -margin + 'px'; |
| 668 if (this.bar_.firstChild) |
| 669 this.bar_.insertBefore(startBox, this.bar_.firstChild); |
| 670 else |
| 671 this.bar_.appendChild(startBox); |
| 672 setTimeout(function() { |
| 673 startBox.style.marginLeft = '0'; |
| 674 }, 0); |
| 675 } else { |
| 676 toRemove.push(startBox); |
| 677 startBox.style.marginLeft = '0'; |
| 678 if (this.bar_.firstChild) |
| 679 this.bar_.insertBefore(startBox, this.bar_.firstChild); |
| 680 else |
| 681 this.bar_.appendChild(startBox); |
| 682 setTimeout(function() { |
| 683 startBox.style.marginLeft = -margin + 'px'; |
| 684 }, 0); |
| 685 } |
| 686 |
| 687 if (firstIndex > 0 && this.selectedIndex_ != firstIndex) { |
| 688 this.bar_.classList.add('fade-left'); |
| 689 } else { |
| 690 this.bar_.classList.remove('fade-left'); |
| 691 } |
| 692 |
| 693 if (lastIndex < this.items_.length - 1 && this.selectedIndex_ != lastIndex) { |
| 694 this.bar_.classList.add('fade-right'); |
| 695 } else { |
| 696 this.bar_.classList.remove('fade-right'); |
| 697 } |
| 708 | 698 |
| 709 this.firstVisibleIndex_ = firstIndex; | 699 this.firstVisibleIndex_ = firstIndex; |
| 710 this.lastVisibleIndex_ = lastIndex; | 700 this.lastVisibleIndex_ = lastIndex; |
| 711 | 701 |
| 712 this.activeBarIndex_ = 1 - this.activeBarIndex_; | 702 var self = this; |
| 713 activeBar = this.bars_[this.activeBarIndex_]; | 703 setTimeout(function() { |
| 714 activeBar.textContent = ''; | 704 for (var i = 0; i < toRemove.length; i++) { |
| 715 for (var index = firstIndex; index <= lastIndex; ++index) { | 705 var index = toRemove[i]; |
| 716 var box = this.items_[index].getBox(this.activeBarIndex_); | 706 if (i < this.firstVisibleIndex_ || i > this.lastVisibleIndex_) { |
| 717 ImageUtil.setAttribute(box, 'inactive', false); | 707 var box = this.items_[index].getBox(0); |
| 718 activeBar.appendChild(box); | 708 if (box.parentNode == this.bar_) |
| 719 } | 709 this.bar_.removeChild(box); |
| 720 | 710 } |
| 721 // Place active bar above inactive after animation is finished. | 711 } |
| 722 setTimeout( | 712 }, 200); |
| 723 ImageUtil.setAttribute.bind(null, activeBar, 'inactive', false), | |
| 724 totalDuration); | |
| 725 }; | 713 }; |
| 726 | 714 |
| 727 Ribbon.prototype.getNextSelectedIndex_ = function(direction) { | 715 Ribbon.prototype.getNextSelectedIndex_ = function(direction) { |
| 728 var index = this.selectedIndex_ + (direction > 0 ? 1 : -1); | 716 var index = this.selectedIndex_ + (direction > 0 ? 1 : -1); |
| 729 if (index == -1) return this.items_.length - 1; | 717 if (index == -1) return this.items_.length - 1; |
| 730 if (index == this.items_.length) return 0; | 718 if (index == this.items_.length) return 0; |
| 731 return index; | 719 return index; |
| 732 }; | 720 }; |
| 733 | 721 |
| 734 Ribbon.prototype.selectNext = function(direction, opt_callback) { | 722 Ribbon.prototype.selectNext = function(direction, opt_callback) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 758 function() { self.slideShowTimeout_ = setTimeout(nextSlide, 5000) }); | 746 function() { self.slideShowTimeout_ = setTimeout(nextSlide, 5000) }); |
| 759 } | 747 } |
| 760 nextSlide(); | 748 nextSlide(); |
| 761 } | 749 } |
| 762 }; | 750 }; |
| 763 | 751 |
| 764 Ribbon.Item = function(index, url, document, selectClosure) { | 752 Ribbon.Item = function(index, url, document, selectClosure) { |
| 765 this.index_ = index; | 753 this.index_ = index; |
| 766 this.url_ = url; | 754 this.url_ = url; |
| 767 | 755 |
| 768 this.boxes_ = []; | 756 this.box_ = document.createElement('div'); |
| 769 this.wrappers_ = []; | 757 this.box_.className = 'ribbon-image'; |
| 770 this.imgs_ = []; | 758 this.box_.addEventListener('click', selectClosure); |
| 771 | 759 |
| 772 for (var i = 0; i < 2; i++) { | 760 this.wrapper_ = document.createElement('div'); |
| 773 var box = document.createElement('div'); | 761 this.wrapper_.className = 'image-wrapper'; |
| 774 box.className = 'ribbon-image'; | 762 this.box_.appendChild(this.wrapper_); |
| 775 box.addEventListener('click', selectClosure); | |
| 776 | 763 |
| 777 var wrapper = document.createElement('div'); | 764 this.img_ = document.createElement('img'); |
| 778 wrapper.className = 'image-wrapper'; | 765 this.wrapper_.appendChild(this.img_); |
| 779 box.appendChild(wrapper); | |
| 780 | |
| 781 var img = document.createElement('img'); | |
| 782 wrapper.appendChild(img); | |
| 783 | |
| 784 this.boxes_.push(box); | |
| 785 this.wrappers_.push(wrapper); | |
| 786 this.imgs_.push(img); | |
| 787 } | |
| 788 | 766 |
| 789 this.original_ = true; | 767 this.original_ = true; |
| 790 this.copyName_ = null; | 768 this.copyName_ = null; |
| 791 }; | 769 }; |
| 792 | 770 |
| 793 Ribbon.Item.prototype.getIndex = function () { return this.index_ }; | 771 Ribbon.Item.prototype.getIndex = function () { return this.index_ }; |
| 794 | 772 |
| 795 Ribbon.Item.prototype.getBox = function (index) { return this.boxes_[index] }; | 773 Ribbon.Item.prototype.getBox = function () { return this.box_ }; |
| 796 | 774 |
| 797 Ribbon.Item.prototype.isOriginal = function () { return this.original_ }; | 775 Ribbon.Item.prototype.isOriginal = function () { return this.original_ }; |
| 798 | 776 |
| 799 Ribbon.Item.prototype.getUrl = function () { return this.url_ }; | 777 Ribbon.Item.prototype.getUrl = function () { return this.url_ }; |
| 800 Ribbon.Item.prototype.setUrl = function (url) { this.url_ = url }; | 778 Ribbon.Item.prototype.setUrl = function (url) { this.url_ = url }; |
| 801 | 779 |
| 802 Ribbon.Item.prototype.getCopyName = function () { return this.copyName_ }; | 780 Ribbon.Item.prototype.getCopyName = function () { return this.copyName_ }; |
| 803 | 781 |
| 804 Ribbon.Item.prototype.isSelected = function() { | 782 Ribbon.Item.prototype.isSelected = function() { |
| 805 return this.boxes_[0].hasAttribute('selected'); | 783 return this.box_.hasAttribute('selected'); |
| 806 }; | 784 }; |
| 807 | 785 |
| 808 Ribbon.Item.prototype.select = function(on) { | 786 Ribbon.Item.prototype.select = function(on) { |
| 809 for (var i = 0; i < 2; i++) { | 787 ImageUtil.setAttribute(this.box_, 'selected', on); |
| 810 ImageUtil.setAttribute(this.boxes_[i], 'selected', on); | |
| 811 } | |
| 812 }; | 788 }; |
| 813 | 789 |
| 814 Ribbon.Item.prototype.updateThumbnail = function(canvas) { | 790 Ribbon.Item.prototype.updateThumbnail = function(canvas) { |
| 815 if (this.canvas_) | 791 if (this.canvas_) |
| 816 return; // The image is being saved, the thumbnail is already up-to-date. | 792 return; // The image is being saved, the thumbnail is already up-to-date. |
| 817 | 793 |
| 818 var metadataEncoder = | 794 var metadataEncoder = |
| 819 ImageEncoder.encodeMetadata(this.getMetadata(), canvas, 1); | 795 ImageEncoder.encodeMetadata(this.getMetadata(), canvas, 1); |
| 820 this.setMetadata(metadataEncoder.getMetadata()); | 796 this.setMetadata(metadataEncoder.getMetadata()); |
| 821 }; | 797 }; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 img.style.marginTop = percent((1 - aspect) / 2); | 988 img.style.marginTop = percent((1 - aspect) / 2); |
| 1013 img.style.marginLeft = 0; | 989 img.style.marginLeft = 0; |
| 1014 } | 990 } |
| 1015 } | 991 } |
| 1016 | 992 |
| 1017 var webkitTransform = transform ? | 993 var webkitTransform = transform ? |
| 1018 ('scaleX(' + transform.scaleX + ') ' + | 994 ('scaleX(' + transform.scaleX + ') ' + |
| 1019 'scaleY(' + transform.scaleY + ') ' + | 995 'scaleY(' + transform.scaleY + ') ' + |
| 1020 'rotate(' + transform.rotate90 * 90 + 'deg)') : | 996 'rotate(' + transform.rotate90 * 90 + 'deg)') : |
| 1021 ''; | 997 ''; |
| 998 this.wrapper_.style.webkitTransform = webkitTransform; |
| 1022 | 999 |
| 1023 for (var i = 0; i < 2; i++) { | 1000 var img = this.img_; |
| 1024 this.wrappers_[i].style.webkitTransform = webkitTransform; | |
| 1025 | 1001 |
| 1026 var img = this.imgs_[i]; | 1002 if (metadata.width && metadata.height) { |
| 1003 var aspect = metadata.width / metadata.height; |
| 1004 if (transform && transform.rotate90) { |
| 1005 aspect = 1 / aspect; |
| 1006 } |
| 1007 resizeToFill(img, aspect); |
| 1008 } else { |
| 1009 // No metadata available, loading the thumbnail first, |
| 1010 // then adjust the size. |
| 1011 img.style.maxWidth = '100%'; |
| 1012 img.style.maxHeight = '100%'; |
| 1027 | 1013 |
| 1028 if (metadata.width && metadata.height) { | 1014 function onLoad(image) { |
| 1029 var aspect = metadata.width / metadata.height; | 1015 image.style.maxWidth = ''; |
| 1030 if (transform && transform.rotate90) { | 1016 image.style.maxHeight = ''; |
| 1031 aspect = 1 / aspect; | 1017 resizeToFill(image, image.width / image.height); |
| 1032 } | 1018 } |
| 1033 resizeToFill(img, aspect); | 1019 img.onload = onLoad.bind(null, img); |
| 1034 } else { | 1020 } |
| 1035 // No metadata available, loading the thumbnail first, | |
| 1036 // then adjust the size. | |
| 1037 img.style.maxWidth = '100%'; | |
| 1038 img.style.maxHeight = '100%'; | |
| 1039 | 1021 |
| 1040 function onLoad(image) { | 1022 img.setAttribute('src', url); |
| 1041 image.style.maxWidth = ''; | |
| 1042 image.style.maxHeight = ''; | |
| 1043 resizeToFill(image, image.width / image.height); | |
| 1044 } | |
| 1045 img.onload = onLoad.bind(null, img); | |
| 1046 } | |
| 1047 | |
| 1048 img.setAttribute('src', url); | |
| 1049 } | |
| 1050 }; | 1023 }; |
| 1051 | 1024 |
| 1052 function ShareMode(editor, container, toolbar, shareActions, | 1025 function ShareMode(editor, container, toolbar, shareActions, |
| 1053 onClick, actionCallback, displayStringFunction) { | 1026 onClick, actionCallback, displayStringFunction) { |
| 1054 ImageEditor.Mode.call(this, 'share'); | 1027 ImageEditor.Mode.call(this, 'share'); |
| 1055 | 1028 |
| 1056 this.message_ = null; | 1029 this.message_ = null; |
| 1057 | 1030 |
| 1058 var doc = container.ownerDocument; | 1031 var doc = container.ownerDocument; |
| 1059 var button = doc.createElement('div'); | 1032 var button = doc.createElement('div'); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1088 ShareMode.prototype.setUp = function() { | 1061 ShareMode.prototype.setUp = function() { |
| 1089 ImageEditor.Mode.prototype.setUp.apply(this, arguments); | 1062 ImageEditor.Mode.prototype.setUp.apply(this, arguments); |
| 1090 ImageUtil.setAttribute(this.menu_, 'hidden', false); | 1063 ImageUtil.setAttribute(this.menu_, 'hidden', false); |
| 1091 ImageUtil.setAttribute(this.button_, 'pressed', false); | 1064 ImageUtil.setAttribute(this.button_, 'pressed', false); |
| 1092 }; | 1065 }; |
| 1093 | 1066 |
| 1094 ShareMode.prototype.cleanUpUI = function() { | 1067 ShareMode.prototype.cleanUpUI = function() { |
| 1095 ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments); | 1068 ImageEditor.Mode.prototype.cleanUpUI.apply(this, arguments); |
| 1096 ImageUtil.setAttribute(this.menu_, 'hidden', true); | 1069 ImageUtil.setAttribute(this.menu_, 'hidden', true); |
| 1097 }; | 1070 }; |
| OLD | NEW |