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