Refactor PDFViewer
to extend an abstract BaseViewer
class
This patch introduces an abstract `BaseViewer` class, that the existing `PDFViewer` then extends. *Please note:* This lays the necessary foundation for the next patch.
This commit is contained in:
parent
d7198d3e17
commit
5fa9cca8dd
@ -17,7 +17,7 @@
|
|||||||
import {
|
import {
|
||||||
animationStarted, DEFAULT_SCALE_VALUE, getPDFFileNameFromURL, isValidRotation,
|
animationStarted, DEFAULT_SCALE_VALUE, getPDFFileNameFromURL, isValidRotation,
|
||||||
MAX_SCALE, MIN_SCALE, noContextMenuHandler, normalizeWheelEventDelta,
|
MAX_SCALE, MIN_SCALE, noContextMenuHandler, normalizeWheelEventDelta,
|
||||||
parseQueryString, ProgressBar, RendererType
|
parseQueryString, PresentationModeState, ProgressBar, RendererType
|
||||||
} from './ui_utils';
|
} from './ui_utils';
|
||||||
import {
|
import {
|
||||||
build, createBlob, getDocument, getFilenameFromUrl, InvalidPDFException,
|
build, createBlob, getDocument, getFilenameFromUrl, InvalidPDFException,
|
||||||
@ -27,7 +27,6 @@ import {
|
|||||||
import { CursorTool, PDFCursorTools } from './pdf_cursor_tools';
|
import { CursorTool, PDFCursorTools } from './pdf_cursor_tools';
|
||||||
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
|
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
|
||||||
import { PDFSidebar, SidebarView } from './pdf_sidebar';
|
import { PDFSidebar, SidebarView } from './pdf_sidebar';
|
||||||
import { PDFViewer, PresentationModeState } from './base_viewer';
|
|
||||||
import { getGlobalEventBus } from './dom_events';
|
import { getGlobalEventBus } from './dom_events';
|
||||||
import { OverlayManager } from './overlay_manager';
|
import { OverlayManager } from './overlay_manager';
|
||||||
import { PasswordPrompt } from './password_prompt';
|
import { PasswordPrompt } from './password_prompt';
|
||||||
@ -40,6 +39,7 @@ import { PDFLinkService } from './pdf_link_service';
|
|||||||
import { PDFOutlineViewer } from './pdf_outline_viewer';
|
import { PDFOutlineViewer } from './pdf_outline_viewer';
|
||||||
import { PDFPresentationMode } from './pdf_presentation_mode';
|
import { PDFPresentationMode } from './pdf_presentation_mode';
|
||||||
import { PDFThumbnailViewer } from './pdf_thumbnail_viewer';
|
import { PDFThumbnailViewer } from './pdf_thumbnail_viewer';
|
||||||
|
import { PDFViewer } from './pdf_viewer';
|
||||||
import { SecondaryToolbar } from './secondary_toolbar';
|
import { SecondaryToolbar } from './secondary_toolbar';
|
||||||
import { Toolbar } from './toolbar';
|
import { Toolbar } from './toolbar';
|
||||||
import { ViewHistory } from './view_history';
|
import { ViewHistory } from './view_history';
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
import { createPromiseCapability, PDFJS } from 'pdfjs-lib';
|
import { createPromiseCapability, PDFJS } from 'pdfjs-lib';
|
||||||
import {
|
import {
|
||||||
CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, getVisibleElements,
|
CSS_UNITS, DEFAULT_SCALE, DEFAULT_SCALE_VALUE, isValidRotation,
|
||||||
isValidRotation, MAX_AUTO_SCALE, NullL10n, RendererType, SCROLLBAR_PADDING,
|
MAX_AUTO_SCALE, NullL10n, PresentationModeState, RendererType,
|
||||||
scrollIntoView, UNKNOWN_SCALE, VERTICAL_PADDING, watchScroll
|
SCROLLBAR_PADDING, UNKNOWN_SCALE, VERTICAL_PADDING, watchScroll
|
||||||
} from './ui_utils';
|
} from './ui_utils';
|
||||||
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
|
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
|
||||||
import { AnnotationLayerBuilder } from './annotation_layer_builder';
|
import { AnnotationLayerBuilder } from './annotation_layer_builder';
|
||||||
@ -26,13 +26,6 @@ import { PDFPageView } from './pdf_page_view';
|
|||||||
import { SimpleLinkService } from './pdf_link_service';
|
import { SimpleLinkService } from './pdf_link_service';
|
||||||
import { TextLayerBuilder } from './text_layer_builder';
|
import { TextLayerBuilder } from './text_layer_builder';
|
||||||
|
|
||||||
const PresentationModeState = {
|
|
||||||
UNKNOWN: 0,
|
|
||||||
NORMAL: 1,
|
|
||||||
CHANGING: 2,
|
|
||||||
FULLSCREEN: 3,
|
|
||||||
};
|
|
||||||
|
|
||||||
const DEFAULT_CACHE_SIZE = 10;
|
const DEFAULT_CACHE_SIZE = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,7 +53,7 @@ const DEFAULT_CACHE_SIZE = 10;
|
|||||||
|
|
||||||
function PDFPageViewBuffer(size) {
|
function PDFPageViewBuffer(size) {
|
||||||
let data = [];
|
let data = [];
|
||||||
this.push = function cachePush(view) {
|
this.push = function(view) {
|
||||||
let i = data.indexOf(view);
|
let i = data.indexOf(view);
|
||||||
if (i >= 0) {
|
if (i >= 0) {
|
||||||
data.splice(i, 1);
|
data.splice(i, 1);
|
||||||
@ -70,7 +63,7 @@ function PDFPageViewBuffer(size) {
|
|||||||
data.shift().destroy();
|
data.shift().destroy();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.resize = function (newSize) {
|
this.resize = function(newSize) {
|
||||||
size = newSize;
|
size = newSize;
|
||||||
while (data.length > size) {
|
while (data.length > size) {
|
||||||
data.shift().destroy();
|
data.shift().destroy();
|
||||||
@ -98,11 +91,16 @@ function isPortraitOrientation(size) {
|
|||||||
* Simple viewer control to display PDF content/pages.
|
* Simple viewer control to display PDF content/pages.
|
||||||
* @implements {IRenderableView}
|
* @implements {IRenderableView}
|
||||||
*/
|
*/
|
||||||
class PDFViewer {
|
class BaseViewer {
|
||||||
/**
|
/**
|
||||||
* @param {PDFViewerOptions} options
|
* @param {PDFViewerOptions} options
|
||||||
*/
|
*/
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
if (this.constructor === BaseViewer) {
|
||||||
|
throw new Error('Cannot initialize BaseViewer.');
|
||||||
|
}
|
||||||
|
this._name = this.constructor.name;
|
||||||
|
|
||||||
this.container = options.container;
|
this.container = options.container;
|
||||||
this.viewer = options.viewer || options.container.firstElementChild;
|
this.viewer = options.viewer || options.container.firstElementChild;
|
||||||
this.eventBus = options.eventBus || getGlobalEventBus();
|
this.eventBus = options.eventBus || getGlobalEventBus();
|
||||||
@ -182,7 +180,7 @@ class PDFViewer {
|
|||||||
|
|
||||||
if (!(0 < val && val <= this.pagesCount)) {
|
if (!(0 < val && val <= this.pagesCount)) {
|
||||||
console.error(
|
console.error(
|
||||||
`PDFViewer._setCurrentPageNumber: "${val}" is out of bounds.`);
|
`${this._name}._setCurrentPageNumber: "${val}" is out of bounds.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,6 +303,10 @@ class PDFViewer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _setDocumentViewerElement() {
|
||||||
|
throw new Error('Not implemented: _setDocumentViewerElement');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param pdfDocument {PDFDocument}
|
* @param pdfDocument {PDFDocument}
|
||||||
*/
|
*/
|
||||||
@ -364,7 +366,7 @@ class PDFViewer {
|
|||||||
textLayerFactory = this;
|
textLayerFactory = this;
|
||||||
}
|
}
|
||||||
let pageView = new PDFPageView({
|
let pageView = new PDFPageView({
|
||||||
container: this.viewer,
|
container: this._setDocumentViewerElement,
|
||||||
eventBus: this.eventBus,
|
eventBus: this.eventBus,
|
||||||
id: pageNum,
|
id: pageNum,
|
||||||
scale,
|
scale,
|
||||||
@ -437,7 +439,7 @@ class PDFViewer {
|
|||||||
} else if (!(labels instanceof Array &&
|
} else if (!(labels instanceof Array &&
|
||||||
this.pdfDocument.numPages === labels.length)) {
|
this.pdfDocument.numPages === labels.length)) {
|
||||||
this._pageLabels = null;
|
this._pageLabels = null;
|
||||||
console.error('PDFViewer.setPageLabels: Invalid page labels.');
|
console.error(`${this._name}.setPageLabels: Invalid page labels.`);
|
||||||
} else {
|
} else {
|
||||||
this._pageLabels = labels;
|
this._pageLabels = labels;
|
||||||
}
|
}
|
||||||
@ -472,6 +474,10 @@ class PDFViewer {
|
|||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null, }) {
|
||||||
|
throw new Error('Not implemented: _scrollIntoView');
|
||||||
|
}
|
||||||
|
|
||||||
_setScaleDispatchEvent(newScale, newValue, preset = false) {
|
_setScaleDispatchEvent(newScale, newValue, preset = false) {
|
||||||
let arg = {
|
let arg = {
|
||||||
source: this,
|
source: this,
|
||||||
@ -560,7 +566,7 @@ class PDFViewer {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error(
|
console.error(
|
||||||
`PDFViewer._setScale: "${value}" is an unknown zoom value.`);
|
`${this._name}._setScale: "${value}" is an unknown zoom value.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._setScaleUpdatePages(scale, value, noScroll, /* preset = */ true);
|
this._setScaleUpdatePages(scale, value, noScroll, /* preset = */ true);
|
||||||
@ -578,7 +584,7 @@ class PDFViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let pageView = this._pages[this._currentPageNumber - 1];
|
let pageView = this._pages[this._currentPageNumber - 1];
|
||||||
scrollIntoView(pageView.div);
|
this._scrollIntoView({ pageDiv: pageView.div, });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -615,7 +621,7 @@ class PDFViewer {
|
|||||||
let pageView = this._pages[pageNumber - 1];
|
let pageView = this._pages[pageNumber - 1];
|
||||||
if (!pageView) {
|
if (!pageView) {
|
||||||
console.error(
|
console.error(
|
||||||
'PDFViewer.scrollPageIntoView: Invalid "pageNumber" parameter.');
|
`${this._name}.scrollPageIntoView: Invalid "pageNumber" parameter.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let x = 0, y = 0;
|
let x = 0, y = 0;
|
||||||
@ -675,7 +681,7 @@ class PDFViewer {
|
|||||||
scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
|
scale = Math.min(Math.abs(widthScale), Math.abs(heightScale));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error(`PDFViewer.scrollPageIntoView: "${dest[1].name}" ` +
|
console.error(`${this._name}.scrollPageIntoView: "${dest[1].name}" ` +
|
||||||
'is not a valid destination type.');
|
'is not a valid destination type.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -687,7 +693,10 @@ class PDFViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (scale === 'page-fit' && !dest[4]) {
|
if (scale === 'page-fit' && !dest[4]) {
|
||||||
scrollIntoView(pageView.div);
|
this._scrollIntoView({
|
||||||
|
pageDiv: pageView.div,
|
||||||
|
pageNumber,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -705,7 +714,17 @@ class PDFViewer {
|
|||||||
left = Math.max(left, 0);
|
left = Math.max(left, 0);
|
||||||
top = Math.max(top, 0);
|
top = Math.max(top, 0);
|
||||||
}
|
}
|
||||||
scrollIntoView(pageView.div, { left, top, });
|
this._scrollIntoView({
|
||||||
|
pageDiv: pageView.div,
|
||||||
|
pageSpot: { left, top, },
|
||||||
|
pageNumber,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_resizeBuffer(numVisiblePages) {
|
||||||
|
let suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE,
|
||||||
|
2 * numVisiblePages + 1);
|
||||||
|
this._buffer.resize(suggestedCacheSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateLocation(firstPage) {
|
_updateLocation(firstPage) {
|
||||||
@ -738,48 +757,7 @@ class PDFViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
let visible = this._getVisiblePages();
|
throw new Error('Not implemented: update');
|
||||||
let visiblePages = visible.views;
|
|
||||||
if (visiblePages.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE,
|
|
||||||
2 * visiblePages.length + 1);
|
|
||||||
this._buffer.resize(suggestedCacheSize);
|
|
||||||
|
|
||||||
this.renderingQueue.renderHighestPriority(visible);
|
|
||||||
|
|
||||||
let currentId = this._currentPageNumber;
|
|
||||||
let firstPage = visible.first;
|
|
||||||
let stillFullyVisible = false;
|
|
||||||
|
|
||||||
for (let i = 0, ii = visiblePages.length; i < ii; ++i) {
|
|
||||||
let page = visiblePages[i];
|
|
||||||
|
|
||||||
if (page.percent < 100) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (page.id === currentId) {
|
|
||||||
stillFullyVisible = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!stillFullyVisible) {
|
|
||||||
currentId = visiblePages[0].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isInPresentationMode) {
|
|
||||||
this._setCurrentPageNumber(currentId);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._updateLocation(firstPage);
|
|
||||||
|
|
||||||
this.eventBus.dispatch('updateviewarea', {
|
|
||||||
source: this,
|
|
||||||
location: this._location,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
containsElement(element) {
|
containsElement(element) {
|
||||||
@ -804,15 +782,7 @@ class PDFViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getVisiblePages() {
|
_getVisiblePages() {
|
||||||
if (!this.isInPresentationMode) {
|
throw new Error('Not implemented: _getVisiblePages');
|
||||||
return getVisibleElements(this.container, this._pages, true);
|
|
||||||
}
|
|
||||||
// The algorithm in getVisibleElements doesn't work in all browsers and
|
|
||||||
// configurations when presentation mode is active.
|
|
||||||
let visible = [];
|
|
||||||
let currentPage = this._pages[this._currentPageNumber - 1];
|
|
||||||
visible.push({ id: currentPage.id, view: currentPage, });
|
|
||||||
return { first: currentPage, last: currentPage, views: visible, };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
@ -974,6 +944,5 @@ class PDFViewer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
PresentationModeState,
|
BaseViewer,
|
||||||
PDFViewer,
|
|
||||||
};
|
};
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var pdfjsLib = require('./pdfjs.js');
|
var pdfjsLib = require('./pdfjs.js');
|
||||||
var pdfjsWebPDFViewer = require('./base_viewer.js');
|
var pdfjsWebPDFViewer = require('./pdf_viewer.js');
|
||||||
var pdfjsWebPDFPageView = require('./pdf_page_view.js');
|
var pdfjsWebPDFPageView = require('./pdf_page_view.js');
|
||||||
var pdfjsWebPDFLinkService = require('./pdf_link_service.js');
|
var pdfjsWebPDFLinkService = require('./pdf_link_service.js');
|
||||||
var pdfjsWebTextLayerBuilder = require('./text_layer_builder.js');
|
var pdfjsWebTextLayerBuilder = require('./text_layer_builder.js');
|
||||||
|
83
web/pdf_viewer.js
Normal file
83
web/pdf_viewer.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* Copyright 2014 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getVisibleElements, scrollIntoView } from './ui_utils';
|
||||||
|
import { BaseViewer } from './base_viewer';
|
||||||
|
import { shadow } from 'pdfjs-lib';
|
||||||
|
|
||||||
|
class PDFViewer extends BaseViewer {
|
||||||
|
get _setDocumentViewerElement() {
|
||||||
|
return shadow(this, '_setDocumentViewerElement', this.viewer);
|
||||||
|
}
|
||||||
|
|
||||||
|
_scrollIntoView({ pageDiv, pageSpot = null, }) {
|
||||||
|
scrollIntoView(pageDiv, pageSpot);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getVisiblePages() {
|
||||||
|
if (!this.isInPresentationMode) {
|
||||||
|
return getVisibleElements(this.container, this._pages, true);
|
||||||
|
}
|
||||||
|
// The algorithm in getVisibleElements doesn't work in all browsers and
|
||||||
|
// configurations when presentation mode is active.
|
||||||
|
let currentPage = this._pages[this._currentPageNumber - 1];
|
||||||
|
let visible = [{ id: currentPage.id, view: currentPage, }];
|
||||||
|
return { first: currentPage, last: currentPage, views: visible, };
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
let visible = this._getVisiblePages();
|
||||||
|
let visiblePages = visible.views, numVisiblePages = visiblePages.length;
|
||||||
|
|
||||||
|
if (numVisiblePages === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this._resizeBuffer(numVisiblePages);
|
||||||
|
|
||||||
|
this.renderingQueue.renderHighestPriority(visible);
|
||||||
|
|
||||||
|
let currentId = this._currentPageNumber;
|
||||||
|
let stillFullyVisible = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < numVisiblePages; ++i) {
|
||||||
|
let page = visiblePages[i];
|
||||||
|
|
||||||
|
if (page.percent < 100) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (page.id === currentId) {
|
||||||
|
stillFullyVisible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stillFullyVisible) {
|
||||||
|
currentId = visiblePages[0].id;
|
||||||
|
}
|
||||||
|
if (!this.isInPresentationMode) {
|
||||||
|
this._setCurrentPageNumber(currentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._updateLocation(visible.first);
|
||||||
|
this.eventBus.dispatch('updateviewarea', {
|
||||||
|
source: this,
|
||||||
|
location: this._location,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
PDFViewer,
|
||||||
|
};
|
@ -25,6 +25,13 @@ const MAX_AUTO_SCALE = 1.25;
|
|||||||
const SCROLLBAR_PADDING = 40;
|
const SCROLLBAR_PADDING = 40;
|
||||||
const VERTICAL_PADDING = 5;
|
const VERTICAL_PADDING = 5;
|
||||||
|
|
||||||
|
const PresentationModeState = {
|
||||||
|
UNKNOWN: 0,
|
||||||
|
NORMAL: 1,
|
||||||
|
CHANGING: 2,
|
||||||
|
FULLSCREEN: 3,
|
||||||
|
};
|
||||||
|
|
||||||
const RendererType = {
|
const RendererType = {
|
||||||
CANVAS: 'canvas',
|
CANVAS: 'canvas',
|
||||||
SVG: 'svg',
|
SVG: 'svg',
|
||||||
@ -661,6 +668,7 @@ export {
|
|||||||
VERTICAL_PADDING,
|
VERTICAL_PADDING,
|
||||||
isValidRotation,
|
isValidRotation,
|
||||||
cloneObj,
|
cloneObj,
|
||||||
|
PresentationModeState,
|
||||||
RendererType,
|
RendererType,
|
||||||
mozL10n,
|
mozL10n,
|
||||||
NullL10n,
|
NullL10n,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user