| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 * Returns the height of the intersection of two rectangles. | 6 * Returns the height of the intersection of two rectangles. |
| 7 * @param {Object} rect1 the first rect | 7 * @param {Object} rect1 the first rect |
| 8 * @param {Object} rect2 the second rect | 8 * @param {Object} rect2 the second rect |
| 9 * @return {number} the height of the intersection of the rects | 9 * @return {number} the height of the intersection of the rects |
| 10 */ | 10 */ |
| 11 function getIntersectionHeight(rect1, rect2) { | 11 function getIntersectionHeight(rect1, rect2) { |
| 12 return Math.max(0, | 12 return Math.max(0, |
| 13 Math.min(rect1.y + rect1.height, rect2.y + rect2.height) - | 13 Math.min(rect1.y + rect1.height, rect2.y + rect2.height) - |
| 14 Math.max(rect1.y, rect2.y)); | 14 Math.max(rect1.y, rect2.y)); |
| 15 } | 15 } |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * Create a new viewport. | 18 * Create a new viewport. |
| 19 * @constructor | 19 * @constructor |
| 20 * @param {Window} window the window | 20 * @param {Window} window the window |
| 21 * @param {Object} sizer is the element which represents the size of the | 21 * @param {Object} sizer is the element which represents the size of the |
| 22 * document in the viewport | 22 * document in the viewport |
| 23 * @param {Function} viewportChangedCallback is run when the viewport changes | 23 * @param {Function} viewportChangedCallback is run when the viewport changes |
| 24 * @param {Function} beforeZoomCallback is run before a change in zoom | 24 * @param {Function} beforeZoomCallback is run before a change in zoom |
| 25 * @param {Function} afterZoomCallback is run after a change in zoom | 25 * @param {Function} afterZoomCallback is run after a change in zoom |
| 26 * @param {number} scrollbarWidth the width of scrollbars on the page | 26 * @param {number} scrollbarWidth the width of scrollbars on the page |
| 27 * @param {number} defaultZoom The default zoom level. | 27 * @param {number} defaultZoom The default zoom level. |
| 28 * @param {number} topToolbarHeight The number of pixels that should initially | |
| 29 * be left blank above the document for the toolbar. | |
| 30 */ | 28 */ |
| 31 function Viewport(window, | 29 function Viewport(window, |
| 32 sizer, | 30 sizer, |
| 33 viewportChangedCallback, | 31 viewportChangedCallback, |
| 34 beforeZoomCallback, | 32 beforeZoomCallback, |
| 35 afterZoomCallback, | 33 afterZoomCallback, |
| 36 scrollbarWidth, | 34 scrollbarWidth, |
| 37 defaultZoom, | 35 defaultZoom) { |
| 38 topToolbarHeight) { | |
| 39 this.window_ = window; | 36 this.window_ = window; |
| 40 this.sizer_ = sizer; | 37 this.sizer_ = sizer; |
| 41 this.viewportChangedCallback_ = viewportChangedCallback; | 38 this.viewportChangedCallback_ = viewportChangedCallback; |
| 42 this.beforeZoomCallback_ = beforeZoomCallback; | 39 this.beforeZoomCallback_ = beforeZoomCallback; |
| 43 this.afterZoomCallback_ = afterZoomCallback; | 40 this.afterZoomCallback_ = afterZoomCallback; |
| 44 this.allowedToChangeZoom_ = false; | 41 this.allowedToChangeZoom_ = false; |
| 45 this.zoom_ = 1; | 42 this.zoom_ = 1; |
| 46 this.documentDimensions_ = null; | 43 this.documentDimensions_ = null; |
| 47 this.pageDimensions_ = []; | 44 this.pageDimensions_ = []; |
| 48 this.scrollbarWidth_ = scrollbarWidth; | 45 this.scrollbarWidth_ = scrollbarWidth; |
| 49 this.fittingType_ = Viewport.FittingType.NONE; | 46 this.fittingType_ = Viewport.FittingType.NONE; |
| 50 this.defaultZoom_ = defaultZoom; | 47 this.defaultZoom_ = defaultZoom; |
| 51 this.topToolbarHeight_ = topToolbarHeight; | |
| 52 | 48 |
| 53 window.addEventListener('scroll', this.updateViewport_.bind(this)); | 49 window.addEventListener('scroll', this.updateViewport_.bind(this)); |
| 54 window.addEventListener('resize', this.resize_.bind(this)); | 50 window.addEventListener('resize', this.resize_.bind(this)); |
| 55 } | 51 } |
| 56 | 52 |
| 57 /** | 53 /** |
| 58 * Enumeration of page fitting types. | 54 * Enumeration of page fitting types. |
| 59 * @enum {string} | 55 * @enum {string} |
| 60 */ | 56 */ |
| 61 Viewport.FittingType = { | 57 Viewport.FittingType = { |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 }, | 132 }, |
| 137 | 133 |
| 138 /** | 134 /** |
| 139 * @private | 135 * @private |
| 140 * Helper function called when the zoomed document size changes. | 136 * Helper function called when the zoomed document size changes. |
| 141 */ | 137 */ |
| 142 contentSizeChanged_: function() { | 138 contentSizeChanged_: function() { |
| 143 if (this.documentDimensions_) { | 139 if (this.documentDimensions_) { |
| 144 this.sizer_.style.width = | 140 this.sizer_.style.width = |
| 145 this.documentDimensions_.width * this.zoom_ + 'px'; | 141 this.documentDimensions_.width * this.zoom_ + 'px'; |
| 146 this.sizer_.style.height = this.documentDimensions_.height * this.zoom_ + | 142 this.sizer_.style.height = |
| 147 this.topToolbarHeight_ + 'px'; | 143 this.documentDimensions_.height * this.zoom_ + 'px'; |
| 148 } | 144 } |
| 149 }, | 145 }, |
| 150 | 146 |
| 151 /** | 147 /** |
| 152 * @private | 148 * @private |
| 153 * Called when the viewport should be updated. | 149 * Called when the viewport should be updated. |
| 154 */ | 150 */ |
| 155 updateViewport_: function() { | 151 updateViewport_: function() { |
| 156 this.viewportChangedCallback_(); | 152 this.viewportChangedCallback_(); |
| 157 }, | 153 }, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 168 else | 164 else |
| 169 this.updateViewport_(); | 165 this.updateViewport_(); |
| 170 }, | 166 }, |
| 171 | 167 |
| 172 /** | 168 /** |
| 173 * @type {Object} the scroll position of the viewport. | 169 * @type {Object} the scroll position of the viewport. |
| 174 */ | 170 */ |
| 175 get position() { | 171 get position() { |
| 176 return { | 172 return { |
| 177 x: this.window_.pageXOffset, | 173 x: this.window_.pageXOffset, |
| 178 y: this.window_.pageYOffset - this.topToolbarHeight_ | 174 y: this.window_.pageYOffset |
| 179 }; | 175 }; |
| 180 }, | 176 }, |
| 181 | 177 |
| 182 /** | 178 /** |
| 183 * Scroll the viewport to the specified position. | 179 * Scroll the viewport to the specified position. |
| 184 * @type {Object} position the position to scroll to. | 180 * @type {Object} position the position to scroll to. |
| 185 */ | 181 */ |
| 186 set position(position) { | 182 set position(position) { |
| 187 this.window_.scrollTo(position.x, position.y + this.topToolbarHeight_); | 183 this.window_.scrollTo(position.x, position.y); |
| 188 }, | 184 }, |
| 189 | 185 |
| 190 /** | 186 /** |
| 191 * @type {Object} the size of the viewport excluding scrollbars. | 187 * @type {Object} the size of the viewport excluding scrollbars. |
| 192 */ | 188 */ |
| 193 get size() { | 189 get size() { |
| 194 var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_); | 190 var needsScrollbars = this.documentNeedsScrollbars_(this.zoom_); |
| 195 var scrollbarWidth = needsScrollbars.vertical ? this.scrollbarWidth_ : 0; | 191 var scrollbarWidth = needsScrollbars.vertical ? this.scrollbarWidth_ : 0; |
| 196 var scrollbarHeight = needsScrollbars.horizontal ? this.scrollbarWidth_ : 0; | 192 var scrollbarHeight = needsScrollbars.horizontal ? this.scrollbarWidth_ : 0; |
| 197 return { | 193 return { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 226 * @private | 222 * @private |
| 227 * Sets the zoom of the viewport. | 223 * Sets the zoom of the viewport. |
| 228 * @param {number} newZoom the zoom level to zoom to. | 224 * @param {number} newZoom the zoom level to zoom to. |
| 229 */ | 225 */ |
| 230 setZoomInternal_: function(newZoom) { | 226 setZoomInternal_: function(newZoom) { |
| 231 if (!this.allowedToChangeZoom_) { | 227 if (!this.allowedToChangeZoom_) { |
| 232 throw 'Called Viewport.setZoomInternal_ without calling ' + | 228 throw 'Called Viewport.setZoomInternal_ without calling ' + |
| 233 'Viewport.mightZoom_.'; | 229 'Viewport.mightZoom_.'; |
| 234 } | 230 } |
| 235 // Record the scroll position (relative to the top-left of the window). | 231 // Record the scroll position (relative to the top-left of the window). |
| 236 var currentScrollPos = { | 232 var currentScrollPos = [ |
| 237 x: this.position.x / this.zoom_, | 233 this.window_.pageXOffset / this.zoom_, |
| 238 y: this.position.y / this.zoom_ | 234 this.window_.pageYOffset / this.zoom_ |
| 239 }; | 235 ]; |
| 240 this.zoom_ = newZoom; | 236 this.zoom_ = newZoom; |
| 241 this.contentSizeChanged_(); | 237 this.contentSizeChanged_(); |
| 242 // Scroll to the scaled scroll position. | 238 // Scroll to the scaled scroll position. |
| 243 this.position = { | 239 this.window_.scrollTo(currentScrollPos[0] * newZoom, |
| 244 x: currentScrollPos.x * newZoom, | 240 currentScrollPos[1] * newZoom); |
| 245 y: currentScrollPos.y * newZoom | |
| 246 }; | |
| 247 }, | 241 }, |
| 248 | 242 |
| 249 /** | 243 /** |
| 250 * Sets the zoom to the given zoom level. | 244 * Sets the zoom to the given zoom level. |
| 251 * @param {number} newZoom the zoom level to zoom to. | 245 * @param {number} newZoom the zoom level to zoom to. |
| 252 */ | 246 */ |
| 253 setZoom: function(newZoom) { | 247 setZoom: function(newZoom) { |
| 254 this.fittingType_ = Viewport.FittingType.NONE; | 248 this.fittingType_ = Viewport.FittingType.NONE; |
| 255 newZoom = Math.max(Viewport.ZOOM_FACTOR_RANGE.min, | 249 newZoom = Math.max(Viewport.ZOOM_FACTOR_RANGE.min, |
| 256 Math.min(newZoom, Viewport.ZOOM_FACTOR_RANGE.max)); | 250 Math.min(newZoom, Viewport.ZOOM_FACTOR_RANGE.max)); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 this.fittingType_ = Viewport.FittingType.FIT_TO_PAGE; | 419 this.fittingType_ = Viewport.FittingType.FIT_TO_PAGE; |
| 426 if (!this.documentDimensions_) | 420 if (!this.documentDimensions_) |
| 427 return; | 421 return; |
| 428 var page = this.getMostVisiblePage(); | 422 var page = this.getMostVisiblePage(); |
| 429 // Fit to the current page's height and the widest page's width. | 423 // Fit to the current page's height and the widest page's width. |
| 430 var dimensions = { | 424 var dimensions = { |
| 431 width: this.documentDimensions_.width, | 425 width: this.documentDimensions_.width, |
| 432 height: this.pageDimensions_[page].height, | 426 height: this.pageDimensions_[page].height, |
| 433 }; | 427 }; |
| 434 this.setZoomInternal_(this.computeFittingZoom_(dimensions, false)); | 428 this.setZoomInternal_(this.computeFittingZoom_(dimensions, false)); |
| 435 if (scrollToTopOfPage) { | 429 if (scrollToTopOfPage) |
| 436 this.position = { | 430 this.window_.scrollTo(0, this.pageDimensions_[page].y * this.zoom_); |
| 437 x: 0, | |
| 438 y: this.pageDimensions_[page].y * this.zoom_ | |
| 439 }; | |
| 440 } | |
| 441 this.updateViewport_(); | 431 this.updateViewport_(); |
| 442 }.bind(this)); | 432 }.bind(this)); |
| 443 }, | 433 }, |
| 444 | 434 |
| 445 /** | 435 /** |
| 446 * Zoom the viewport so that a page consumes the entire viewport. Also scrolls | 436 * Zoom the viewport so that a page consumes the entire viewport. Also scrolls |
| 447 * the viewport to the top of the current page. | 437 * the viewport to the top of the current page. |
| 448 */ | 438 */ |
| 449 fitToPage: function() { | 439 fitToPage: function() { |
| 450 this.fitToPageInternal_(true); | 440 this.fitToPageInternal_(true); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 488 */ | 478 */ |
| 489 goToPage: function(page) { | 479 goToPage: function(page) { |
| 490 this.mightZoom_(function() { | 480 this.mightZoom_(function() { |
| 491 if (this.pageDimensions_.length === 0) | 481 if (this.pageDimensions_.length === 0) |
| 492 return; | 482 return; |
| 493 if (page < 0) | 483 if (page < 0) |
| 494 page = 0; | 484 page = 0; |
| 495 if (page >= this.pageDimensions_.length) | 485 if (page >= this.pageDimensions_.length) |
| 496 page = this.pageDimensions_.length - 1; | 486 page = this.pageDimensions_.length - 1; |
| 497 var dimensions = this.pageDimensions_[page]; | 487 var dimensions = this.pageDimensions_[page]; |
| 498 var toolbarOffset = 0; | 488 this.window_.scrollTo(dimensions.x * this.zoom_, |
| 499 // Unless we're in fit to page mode, scroll above the page by | 489 dimensions.y * this.zoom_); |
| 500 // |this.topToolbarHeight_| so that the toolbar isn't covering it | |
| 501 // initially. | |
| 502 if (this.fittingType_ != Viewport.FittingType.FIT_TO_PAGE) | |
| 503 toolbarOffset = this.topToolbarHeight_; | |
| 504 this.position = { | |
| 505 x: dimensions.x * this.zoom_, | |
| 506 y: dimensions.y * this.zoom_ - toolbarOffset | |
| 507 }; | |
| 508 this.updateViewport_(); | 490 this.updateViewport_(); |
| 509 }.bind(this)); | 491 }.bind(this)); |
| 510 }, | 492 }, |
| 511 | 493 |
| 512 /** | 494 /** |
| 513 * Set the dimensions of the document. | 495 * Set the dimensions of the document. |
| 514 * @param {Object} documentDimensions the dimensions of the document | 496 * @param {Object} documentDimensions the dimensions of the document |
| 515 */ | 497 */ |
| 516 setDocumentDimensions: function(documentDimensions) { | 498 setDocumentDimensions: function(documentDimensions) { |
| 517 this.mightZoom_(function() { | 499 this.mightZoom_(function() { |
| 518 var initialDimensions = !this.documentDimensions_; | 500 var initialDimensions = !this.documentDimensions_; |
| 519 this.documentDimensions_ = documentDimensions; | 501 this.documentDimensions_ = documentDimensions; |
| 520 this.pageDimensions_ = this.documentDimensions_.pageDimensions; | 502 this.pageDimensions_ = this.documentDimensions_.pageDimensions; |
| 521 if (initialDimensions) { | 503 if (initialDimensions) { |
| 522 this.setZoomInternal_( | 504 this.setZoomInternal_( |
| 523 Math.min(this.defaultZoom_, | 505 Math.min(this.defaultZoom_, |
| 524 this.computeFittingZoom_(this.documentDimensions_, true))); | 506 this.computeFittingZoom_(this.documentDimensions_, true))); |
| 525 this.position = { | 507 this.window_.scrollTo(0, 0); |
| 526 x: 0, | |
| 527 y: -this.topToolbarHeight_ | |
| 528 }; | |
| 529 } | 508 } |
| 530 this.contentSizeChanged_(); | 509 this.contentSizeChanged_(); |
| 531 this.resize_(); | 510 this.resize_(); |
| 532 }.bind(this)); | 511 }.bind(this)); |
| 533 }, | 512 }, |
| 534 | 513 |
| 535 /** | 514 /** |
| 536 * Get the coordinates of the page contents (excluding the page shadow) | 515 * Get the coordinates of the page contents (excluding the page shadow) |
| 537 * relative to the screen. | 516 * relative to the screen. |
| 538 * @param {number} page the index of the page to get the rect for. | 517 * @param {number} page the index of the page to get the rect for. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 spaceOnLeft = Math.max(spaceOnLeft, 0); | 553 spaceOnLeft = Math.max(spaceOnLeft, 0); |
| 575 | 554 |
| 576 return { | 555 return { |
| 577 x: x * this.zoom_ + spaceOnLeft - this.window_.pageXOffset, | 556 x: x * this.zoom_ + spaceOnLeft - this.window_.pageXOffset, |
| 578 y: insetDimensions.y * this.zoom_ - this.window_.pageYOffset, | 557 y: insetDimensions.y * this.zoom_ - this.window_.pageYOffset, |
| 579 width: insetDimensions.width * this.zoom_, | 558 width: insetDimensions.width * this.zoom_, |
| 580 height: insetDimensions.height * this.zoom_ | 559 height: insetDimensions.height * this.zoom_ |
| 581 }; | 560 }; |
| 582 } | 561 } |
| 583 }; | 562 }; |
| OLD | NEW |