blob: 85578a383dfe8fa344883b867d75d60cc899a112 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @typedef {{accessibility: Function,
* documentLoadComplete: Function,
* getHeight: Function,
* getHorizontalScrollbarThickness: Function,
* getPageLocationNormalized: Function,
* getVerticalScrollbarThickness: Function,
* getWidth: Function,
* getZoomLevel: Function,
* goToPage: Function,
* grayscale: Function,
* loadPreviewPage: Function,
* onload: Function,
* onPluginSizeChanged: Function,
* onScroll: Function,
* pageXOffset: Function,
* pageYOffset: Function,
* printPreviewPageCount: Function,
* reload: Function,
* removePrintButton: Function,
* resetPrintPreviewUrl: Function,
* sendKeyEvent: Function,
* setPageNumbers: Function,
* setPageXOffset: Function,
* setPageYOffset: Function,
* setZoomLevel: Function,
* fitToHeight: Function,
* fitToWidth: Function,
* zoomIn: Function,
* zoomOut: Function}}
*/
print_preview.PDFPlugin;
cr.define('print_preview', function() {
'use strict';
/**
* Creates a PreviewArea object. It represents the area where the preview
* document is displayed.
* @param {!print_preview.DestinationStore} destinationStore Used to get the
* currently selected destination.
* @param {!print_preview.PrintTicketStore} printTicketStore Used to get
* information about how the preview should be displayed.
* @param {!print_preview.NativeLayer} nativeLayer Needed to communicate with
* Chromium's preview generation system.
* @param {!print_preview.DocumentInfo} documentInfo Document data model.
* @constructor
* @extends {print_preview.Component}
*/
function PreviewArea(
destinationStore, printTicketStore, nativeLayer, documentInfo) {
print_preview.Component.call(this);
// TODO(rltoscano): Understand the dependencies of printTicketStore needed
// here, and add only those here (not the entire print ticket store).
/**
* Used to get the currently selected destination.
* @type {!print_preview.DestinationStore}
* @private
*/
this.destinationStore_ = destinationStore;
/**
* Used to get information about how the preview should be displayed.
* @type {!print_preview.PrintTicketStore}
* @private
*/
this.printTicketStore_ = printTicketStore;
/**
* Used to contruct the preview generator.
* @type {!print_preview.NativeLayer}
* @private
*/
this.nativeLayer_ = nativeLayer;
/**
* Document data model.
* @type {!print_preview.DocumentInfo}
* @private
*/
this.documentInfo_ = documentInfo;
/**
* Used to read generated page previews.
* @type {print_preview.PreviewGenerator}
* @private
*/
this.previewGenerator_ = null;
/**
* The embedded pdf plugin object. It's value is null if not yet loaded.
* @type {HTMLEmbedElement|print_preview.PDFPlugin}
* @private
*/
this.plugin_ = null;
/**
* Custom margins component superimposed on the preview plugin.
* @type {!print_preview.MarginControlContainer}
* @private
*/
this.marginControlContainer_ = new print_preview.MarginControlContainer(
this.documentInfo_,
this.printTicketStore_.marginsType,
this.printTicketStore_.customMargins,
this.printTicketStore_.measurementSystem);
this.addChild(this.marginControlContainer_);
/**
* Current zoom level as a percentage.
* @type {?number}
* @private
*/
this.zoomLevel_ = null;
/**
* Current page offset which can be used to calculate scroll amount.
* @type {print_preview.Coordinate2d}
* @private
*/
this.pageOffset_ = null;
/**
* Whether the plugin has finished reloading.
* @type {boolean}
* @private
*/
this.isPluginReloaded_ = false;
/**
* Whether the document preview is ready.
* @type {boolean}
* @private
*/
this.isDocumentReady_ = false;
/**
* Timeout object used to display a loading message if the preview is taking
* a long time to generate.
* @type {?number}
* @private
*/
this.loadingTimeout_ = null;
/**
* Overlay element.
* @type {HTMLElement}
* @private
*/
this.overlayEl_ = null;
/**
* The "Open system dialog" button.
* @type {HTMLButtonElement}
* @private
*/
this.openSystemDialogButton_ = null;
};
/**
* Event types dispatched by the preview area.
* @enum {string}
*/
PreviewArea.EventType = {
// Dispatched when the "Open system dialog" button is clicked.
OPEN_SYSTEM_DIALOG_CLICK:
'print_preview.PreviewArea.OPEN_SYSTEM_DIALOG_CLICK',
// Dispatched when the document preview is complete.
PREVIEW_GENERATION_DONE:
'print_preview.PreviewArea.PREVIEW_GENERATION_DONE',
// Dispatched when the document preview failed to be generated.
PREVIEW_GENERATION_FAIL:
'print_preview.PreviewArea.PREVIEW_GENERATION_FAIL',
// Dispatched when a new document preview is being generated.
PREVIEW_GENERATION_IN_PROGRESS:
'print_preview.PreviewArea.PREVIEW_GENERATION_IN_PROGRESS'
};
/**
* CSS classes used by the preview area.
* @enum {string}
* @private
*/
PreviewArea.Classes_ = {
COMPATIBILITY_OBJECT: 'preview-area-compatibility-object',
OUT_OF_PROCESS_COMPATIBILITY_OBJECT:
'preview-area-compatibility-object-out-of-process',
CUSTOM_MESSAGE_TEXT: 'preview-area-custom-message-text',
MESSAGE: 'preview-area-message',
INVISIBLE: 'invisible',
OPEN_SYSTEM_DIALOG_BUTTON: 'preview-area-open-system-dialog-button',
OPEN_SYSTEM_DIALOG_BUTTON_THROBBER:
'preview-area-open-system-dialog-button-throbber',
OVERLAY: 'preview-area-overlay-layer'
};
/**
* Enumeration of IDs shown in the preview area.
* @enum {string}
* @private
*/
PreviewArea.MessageId_ = {
CUSTOM: 'custom',
LOADING: 'loading',
PREVIEW_FAILED: 'preview-failed'
};
/**
* Enumeration of PDF plugin types for print preview.
* @enum {string}
* @private
*/
PreviewArea.PluginType_ = {
// TODO(raymes): Remove all references to the IN_PROCESS plugin once it is
// removed.
IN_PROCESS: 'in-process',
OUT_OF_PROCESS: 'out-of-process',
NONE: 'none'
};
/**
* Maps message IDs to the CSS class that contains them.
* @type {Object.<print_preview.PreviewArea.MessageId_, string>}
* @private
*/
PreviewArea.MessageIdClassMap_ = {};
PreviewArea.MessageIdClassMap_[PreviewArea.MessageId_.CUSTOM] =
'preview-area-custom-message';
PreviewArea.MessageIdClassMap_[PreviewArea.MessageId_.LOADING] =
'preview-area-loading-message';
PreviewArea.MessageIdClassMap_[PreviewArea.MessageId_.PREVIEW_FAILED] =
'preview-area-preview-failed-message';
/**
* Amount of time in milliseconds to wait after issueing a new preview before
* the loading message is shown.
* @type {number}
* @const
* @private
*/
PreviewArea.LOADING_TIMEOUT_ = 200;
PreviewArea.prototype = {
__proto__: print_preview.Component.prototype,
/**
* Should only be called after calling this.render().
* @return {boolean} Whether the preview area has a compatible plugin to
* display the print preview in.
*/
get hasCompatiblePlugin() {
return this.previewGenerator_ != null;
},
/**
* Processes a keyboard event that could possibly be used to change state of
* the preview plugin.
* @param {KeyboardEvent} e Keyboard event to process.
*/
handleDirectionalKeyEvent: function(e) {
// Make sure the PDF plugin is there.
// We only care about: PageUp, PageDown, Left, Up, Right, Down.
// If the user is holding a modifier key, ignore.
if (!this.plugin_ ||
!arrayContains([33, 34, 37, 38, 39, 40], e.keyCode) ||
e.metaKey || e.altKey || e.shiftKey || e.ctrlKey) {
return;
}
// Don't handle the key event for these elements.
var tagName = document.activeElement.tagName;
if (arrayContains(['INPUT', 'SELECT', 'EMBED'], tagName)) {
return;
}
// For the most part, if any div of header was the last clicked element,
// then the active element is the body. Starting with the last clicked
// element, and work up the DOM tree to see if any element has a
// scrollbar. If there exists a scrollbar, do not handle the key event
// here.
var element = e.target;
while (element) {
if (element.scrollHeight > element.clientHeight ||
element.scrollWidth > element.clientWidth) {
return;
}
element = element.parentElement;
}
// No scroll bar anywhere, or the active element is something else, like a
// button. Note: buttons have a bigger scrollHeight than clientHeight.
this.plugin_.sendKeyEvent(e.keyCode);
e.preventDefault();
},
/**
* Shows a custom message on the preview area's overlay.
* @param {string} message Custom message to show.
*/
showCustomMessage: function(message) {
this.showMessage_(PreviewArea.MessageId_.CUSTOM, message);
},
/** @override */
enterDocument: function() {
print_preview.Component.prototype.enterDocument.call(this);
this.tracker.add(
assert(this.openSystemDialogButton_),
'click',
this.onOpenSystemDialogButtonClick_.bind(this));
this.tracker.add(
this.printTicketStore_,
print_preview.PrintTicketStore.EventType.INITIALIZE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_,
print_preview.PrintTicketStore.EventType.TICKET_CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_,
print_preview.PrintTicketStore.EventType.CAPABILITIES_CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_,
print_preview.PrintTicketStore.EventType.DOCUMENT_CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.color,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.cssBackground,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.customMargins,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.fitToPage,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.headerFooter,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.landscape,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.marginsType,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.pageRange,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.tracker.add(
this.printTicketStore_.selectionOnly,
print_preview.ticket_items.TicketItem.EventType.CHANGE,
this.onTicketChange_.bind(this));
this.pluginType_ = this.getPluginType_();
if (this.pluginType_ != PreviewArea.PluginType_.NONE) {
this.previewGenerator_ = new print_preview.PreviewGenerator(
this.destinationStore_,
this.printTicketStore_,
this.nativeLayer_,
this.documentInfo_);
this.tracker.add(
this.previewGenerator_,
print_preview.PreviewGenerator.EventType.PREVIEW_START,
this.onPreviewStart_.bind(this));
this.tracker.add(
this.previewGenerator_,
print_preview.PreviewGenerator.EventType.PAGE_READY,
this.onPagePreviewReady_.bind(this));
this.tracker.add(
this.previewGenerator_,
print_preview.PreviewGenerator.EventType.FAIL,
this.onPreviewGenerationFail_.bind(this));
this.tracker.add(
this.previewGenerator_,
print_preview.PreviewGenerator.EventType.DOCUMENT_READY,
this.onDocumentReady_.bind(this));
} else {
this.showCustomMessage(loadTimeData.getString('noPlugin'));
}
},
/** @override */
exitDocument: function() {
print_preview.Component.prototype.exitDocument.call(this);
if (this.previewGenerator_) {
this.previewGenerator_.removeEventListeners();
}
this.overlayEl_ = null;
this.openSystemDialogButton_ = null;
},
/** @override */
decorateInternal: function() {
this.marginControlContainer_.decorate(this.getElement());
this.overlayEl_ = this.getElement().getElementsByClassName(
PreviewArea.Classes_.OVERLAY)[0];
this.openSystemDialogButton_ = this.getElement().getElementsByClassName(
PreviewArea.Classes_.OPEN_SYSTEM_DIALOG_BUTTON)[0];
},
/**
* Checks to see if a suitable plugin for rendering the preview exists. If
* one does not exist, then an error message will be displayed.
* @return {string} A string constant indicating whether Chromium has a
* plugin for rendering the preview.
* PreviewArea.PluginType_.IN_PROCESS for an in-process plugin
* PreviewArea.PluginType_.OUT_OF_PROCESS for an out-of-process plugin
* PreviewArea.PluginType_.NONE if no plugin is available.
* @private
*/
getPluginType_: function() {
// TODO(raymes): Remove the in-process check after we remove the
// in-process plugin. Change this function back to
// checkPluginCompatibility_().
/** @type {print_preview.PDFPlugin} */
var compatObj = this.getElement().getElementsByClassName(
PreviewArea.Classes_.COMPATIBILITY_OBJECT)[0];
var isCompatible =
compatObj.onload &&
compatObj.goToPage &&
compatObj.removePrintButton &&
compatObj.loadPreviewPage &&
compatObj.printPreviewPageCount &&
compatObj.resetPrintPreviewUrl &&
compatObj.onPluginSizeChanged &&
compatObj.onScroll &&
compatObj.pageXOffset &&
compatObj.pageYOffset &&
compatObj.setZoomLevel &&
compatObj.setPageNumbers &&
compatObj.setPageXOffset &&
compatObj.setPageYOffset &&
compatObj.getHorizontalScrollbarThickness &&
compatObj.getVerticalScrollbarThickness &&
compatObj.getPageLocationNormalized &&
compatObj.getHeight &&
compatObj.getWidth;
compatObj.parentElement.removeChild(compatObj);
// TODO(raymes): It's harder to test compatibility of the out of process
// plugin because it's asynchronous. We could do a better job at some
// point.
var oopCompatObj = this.getElement().getElementsByClassName(
PreviewArea.Classes_.OUT_OF_PROCESS_COMPATIBILITY_OBJECT)[0];
var isOOPCompatible = oopCompatObj.postMessage;
oopCompatObj.parentElement.removeChild(oopCompatObj);
if (isCompatible)
return PreviewArea.PluginType_.IN_PROCESS;
if (isOOPCompatible)
return PreviewArea.PluginType_.OUT_OF_PROCESS;
return PreviewArea.PluginType_.NONE;
},
/**
* Shows a given message on the overlay.
* @param {!print_preview.PreviewArea.MessageId_} messageId ID of the
* message to show.
* @param {string=} opt_message Optional message to show that can be used
* by some message IDs.
* @private
*/
showMessage_: function(messageId, opt_message) {
// Hide all messages.
var messageEls = this.getElement().getElementsByClassName(
PreviewArea.Classes_.MESSAGE);
for (var i = 0, messageEl; messageEl = messageEls[i]; i++) {
setIsVisible(messageEl, false);
}
// Disable jumping animation to conserve cycles.
var jumpingDotsEl = this.getElement().querySelector(
'.preview-area-loading-message-jumping-dots');
jumpingDotsEl.classList.remove('jumping-dots');
// Show specific message.
if (messageId == PreviewArea.MessageId_.CUSTOM) {
var customMessageTextEl = this.getElement().getElementsByClassName(
PreviewArea.Classes_.CUSTOM_MESSAGE_TEXT)[0];
customMessageTextEl.textContent = opt_message;
} else if (messageId == PreviewArea.MessageId_.LOADING) {
jumpingDotsEl.classList.add('jumping-dots');
}
var messageEl = this.getElement().getElementsByClassName(
PreviewArea.MessageIdClassMap_[messageId])[0];
setIsVisible(messageEl, true);
// Show overlay.
this.overlayEl_.classList.remove(PreviewArea.Classes_.INVISIBLE);
},
/**
* Hides the message overlay.
* @private
*/
hideOverlay_: function() {
this.overlayEl_.classList.add(PreviewArea.Classes_.INVISIBLE);
// Disable jumping animation to conserve cycles.
var jumpingDotsEl = this.getElement().querySelector(
'.preview-area-loading-message-jumping-dots');
jumpingDotsEl.classList.remove('jumping-dots');
},
/**
* Creates a preview plugin and adds it to the DOM.
* @param {string} srcUrl Initial URL of the plugin.
* @private
*/
createPlugin_: function(srcUrl) {
if (this.plugin_) {
console.warn('Pdf preview plugin already created');
return;
}
if (this.pluginType_ == PreviewArea.PluginType_.IN_PROCESS) {
this.plugin_ = assertInstanceof(document.createElement('embed'),
HTMLEmbedElement);
this.plugin_.setAttribute(
'type', 'application/x-google-chrome-print-preview-pdf');
this.plugin_.setAttribute('src', srcUrl);
} else {
this.plugin_ = /** @type {print_preview.PDFPlugin} */(
PDFCreateOutOfProcessPlugin(srcUrl));
}
this.plugin_.setAttribute('class', 'preview-area-plugin');
this.plugin_.setAttribute('aria-live', 'polite');
this.plugin_.setAttribute('aria-atomic', 'true');
// NOTE: The plugin's 'id' field must be set to 'pdf-viewer' since
// chrome/renderer/printing/print_web_view_helper.cc actually references
// it.
this.plugin_.setAttribute('id', 'pdf-viewer');
this.getChildElement('.preview-area-plugin-wrapper').
appendChild(/** @type {Node} */(this.plugin_));
if (this.pluginType_ == PreviewArea.PluginType_.OUT_OF_PROCESS) {
var pageNumbers =
this.printTicketStore_.pageRange.getPageNumberSet().asArray();
var grayscale = !this.printTicketStore_.color.getValue();
this.plugin_.setLoadCallback(this.onPluginLoad_.bind(this));
this.plugin_.setViewportChangedCallback(
this.onPreviewVisualStateChange_.bind(this));
this.plugin_.resetPrintPreviewMode(srcUrl, grayscale, pageNumbers,
this.documentInfo_.isModifiable);
} else {
global['onPreviewPluginLoad'] = this.onPluginLoad_.bind(this);
(/** @type {print_preview.PDFPlugin} */(this.plugin_)).
onload('onPreviewPluginLoad()');
global['onPreviewPluginVisualStateChange'] =
this.onPreviewVisualStateChange_.bind(this);
this.plugin_.onScroll('onPreviewPluginVisualStateChange()');
this.plugin_.onPluginSizeChanged('onPreviewPluginVisualStateChange()');
this.plugin_.removePrintButton();
this.plugin_.grayscale(!this.printTicketStore_.color.getValue());
}
},
/**
* Dispatches a PREVIEW_GENERATION_DONE event if all conditions are met.
* @private
*/
dispatchPreviewGenerationDoneIfReady_: function() {
if (this.isDocumentReady_ && this.isPluginReloaded_) {
cr.dispatchSimpleEvent(
this, PreviewArea.EventType.PREVIEW_GENERATION_DONE);
this.marginControlContainer_.showMarginControlsIfNeeded();
}
},
/**
* Called when the open-system-dialog button is clicked. Disables the
* button, shows the throbber, and dispatches the OPEN_SYSTEM_DIALOG_CLICK
* event.
* @private
*/
onOpenSystemDialogButtonClick_: function() {
this.openSystemDialogButton_.disabled = true;
var openSystemDialogThrobber = this.getElement().getElementsByClassName(
PreviewArea.Classes_.OPEN_SYSTEM_DIALOG_BUTTON_THROBBER)[0];
setIsVisible(openSystemDialogThrobber, true);
cr.dispatchSimpleEvent(
this, PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK);
},
/**
* Called when the print ticket changes. Updates the preview.
* @private
*/
onTicketChange_: function() {
if (this.previewGenerator_ && this.previewGenerator_.requestPreview()) {
cr.dispatchSimpleEvent(
this, PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS);
if (this.loadingTimeout_ == null) {
this.loadingTimeout_ = setTimeout(
this.showMessage_.bind(this, PreviewArea.MessageId_.LOADING),
PreviewArea.LOADING_TIMEOUT_);
}
} else {
this.marginControlContainer_.showMarginControlsIfNeeded();
}
},
/**
* Called when the preview generator begins loading the preview.
* @param {Event} event Contains the URL to initialize the plugin to.
* @private
*/
onPreviewStart_: function(event) {
this.isDocumentReady_ = false;
this.isPluginReloaded_ = false;
if (!this.plugin_) {
this.createPlugin_(event.previewUrl);
} else {
if (this.pluginType_ == PreviewArea.PluginType_.OUT_OF_PROCESS) {
var grayscale = !this.printTicketStore_.color.getValue();
var pageNumbers =
this.printTicketStore_.pageRange.getPageNumberSet().asArray();
var url = event.previewUrl;
this.plugin_.resetPrintPreviewMode(url, grayscale, pageNumbers,
this.documentInfo_.isModifiable);
} else if (this.pluginType_ == PreviewArea.PluginType_.IN_PROCESS) {
this.plugin_.goToPage('0');
this.plugin_.resetPrintPreviewUrl(event.previewUrl);
this.plugin_.reload();
this.plugin_.grayscale(!this.printTicketStore_.color.getValue());
}
}
cr.dispatchSimpleEvent(
this, PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS);
},
/**
* Called when a page preview has been generated. Updates the plugin with
* the new page.
* @param {Event} event Contains information about the page preview.
* @private
*/
onPagePreviewReady_: function(event) {
this.plugin_.loadPreviewPage(event.previewUrl, event.previewIndex);
},
/**
* Called when the preview generation is complete and the document is ready
* to print.
* @private
*/
onDocumentReady_: function(event) {
this.isDocumentReady_ = true;
this.dispatchPreviewGenerationDoneIfReady_();
},
/**
* Called when the generation of a preview fails. Shows an error message.
* @private
*/
onPreviewGenerationFail_: function() {
if (this.loadingTimeout_) {
clearTimeout(this.loadingTimeout_);
this.loadingTimeout_ = null;
}
this.showMessage_(PreviewArea.MessageId_.PREVIEW_FAILED);
cr.dispatchSimpleEvent(
this, PreviewArea.EventType.PREVIEW_GENERATION_FAIL);
},
/**
* Called when the plugin loads. This is a consequence of calling
* plugin.reload(). Certain plugin state can only be set after the plugin
* has loaded.
* @private
*/
onPluginLoad_: function() {
if (this.loadingTimeout_) {
clearTimeout(this.loadingTimeout_);
this.loadingTimeout_ = null;
}
if (this.pluginType_ == PreviewArea.PluginType_.IN_PROCESS) {
// Setting the plugin's page count can only be called after the plugin
// is loaded and the document must be modifiable.
if (this.documentInfo_.isModifiable) {
this.plugin_.printPreviewPageCount(
this.printTicketStore_.pageRange.getPageNumberSet().size);
}
this.plugin_.setPageNumbers(JSON.stringify(
this.printTicketStore_.pageRange.getPageNumberSet().asArray()));
if (this.zoomLevel_ != null && this.pageOffset_ != null) {
this.plugin_.setZoomLevel(this.zoomLevel_);
this.plugin_.setPageXOffset(this.pageOffset_.x);
this.plugin_.setPageYOffset(this.pageOffset_.y);
} else {
this.plugin_.fitToHeight();
}
}
this.hideOverlay_();
this.isPluginReloaded_ = true;
this.dispatchPreviewGenerationDoneIfReady_();
},
/**
* Called when the preview plugin's visual state has changed. This is a
* consequence of scrolling or zooming the plugin. Updates the custom
* margins component if shown.
* @private
*/
onPreviewVisualStateChange_: function(pageX,
pageY,
pageWidth,
viewportWidth,
viewportHeight) {
if (this.pluginType_ == PreviewArea.PluginType_.IN_PROCESS) {
if (this.isPluginReloaded_) {
this.zoomLevel_ = this.plugin_.getZoomLevel();
this.pageOffset_ = new print_preview.Coordinate2d(
this.plugin_.pageXOffset(), this.plugin_.pageYOffset());
}
var pageLocationNormalizedStr =
this.plugin_.getPageLocationNormalized();
if (!pageLocationNormalizedStr) {
return;
}
var normalized = pageLocationNormalizedStr.split(';');
var pluginWidth = this.plugin_.getWidth();
var pluginHeight = this.plugin_.getHeight();
var verticalScrollbarThickness =
this.plugin_.getVerticalScrollbarThickness();
var horizontalScrollbarThickness =
this.plugin_.getHorizontalScrollbarThickness();
var translationTransform = new print_preview.Coordinate2d(
parseFloat(normalized[0]) * pluginWidth,
parseFloat(normalized[1]) * pluginHeight);
this.marginControlContainer_.updateTranslationTransform(
translationTransform);
var pageWidthInPixels = parseFloat(normalized[2]) * pluginWidth;
this.marginControlContainer_.updateScaleTransform(
pageWidthInPixels / this.documentInfo_.pageSize.width);
this.marginControlContainer_.updateClippingMask(
new print_preview.Size(
pluginWidth - verticalScrollbarThickness,
pluginHeight - horizontalScrollbarThickness));
} else if (this.pluginType_ == PreviewArea.PluginType_.OUT_OF_PROCESS) {
this.marginControlContainer_.updateTranslationTransform(
new print_preview.Coordinate2d(pageX, pageY));
this.marginControlContainer_.updateScaleTransform(
pageWidth / this.documentInfo_.pageSize.width);
this.marginControlContainer_.updateClippingMask(
new print_preview.Size(viewportWidth, viewportHeight));
}
}
};
// Export
return {
PreviewArea: PreviewArea
};
});