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 |