diff options
author | dpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-12 08:57:22 +0000 |
---|---|---|
committer | dpapad@chromium.org <dpapad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-12 08:57:22 +0000 |
commit | 05b14b552fa44d27b7f0d12c19f9a39064c85868 (patch) | |
tree | 85079247735df754a321f3da6dee7ced3fdb181f /chrome/browser/resources/print_preview | |
parent | b691a100e6ff4aec4880a6957d6a79921ac53eda (diff) | |
download | chromium_src-05b14b552fa44d27b7f0d12c19f9a39064c85868.zip chromium_src-05b14b552fa44d27b7f0d12c19f9a39064c85868.tar.gz chromium_src-05b14b552fa44d27b7f0d12c19f9a39064c85868.tar.bz2 |
Print Preview: Adding UI for margin settings.
BUG=69337
TEST=Open print preview. Margin options should be available.
Review URL: http://codereview.chromium.org/7891016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105044 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/resources/print_preview')
12 files changed, 1370 insertions, 70 deletions
diff --git a/chrome/browser/resources/print_preview/margin_line.js b/chrome/browser/resources/print_preview/margin_line.js new file mode 100644 index 0000000..f8999c1 --- /dev/null +++ b/chrome/browser/resources/print_preview/margin_line.js @@ -0,0 +1,181 @@ +// Copyright (c) 2011 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. + +cr.define('print_preview', function() { + 'strict'; + + function MarginLine(groupName) { + var line = document.createElement('div'); + line.__proto__ = MarginLine.prototype; + line.className = MarginLine.CSS_CLASS_DRAGGABLE_AREA; + // @type {string} Specifies which margin this line refers to. + line.marginGroup = groupName; + // @type {print_preview.Rect} A rectangle describing the values of all + // margins. + line.rectangle = null; + // @type {HTMLDivElement} The dotted line representing the margin. + line.visibleLine = document.createElement('div'); + line.visibleLine.className = MarginLine.CSS_CLASS_MARGIN_LINE; + + line.appendChild(line.visibleLine); + return line; + } + + MarginLine.CSS_CLASS_MARGIN_LINE = 'margin-line'; + MarginLine.CSS_CLASS_DRAGGABLE_AREA = 'draggable-area'; + // Width of the clickable region around each margin line in screen pixels. + MarginLine.CLICKABLE_REGION = 20; + + MarginLine.prototype = { + __proto__: HTMLDivElement.prototype, + + update: function(marginsRectangle) { + this.rectangle = this.getCoordinates_(marginsRectangle); + }, + + /** + * Draws |this| on screen. Essentially two divs are being drawn, the drag + * control area (invisible) and the dotted margin line (visible). + */ + draw: function() { + this.drawDraggableArea_(); + this.drawDottedLine_(); + }, + + /** + * Draws the dotted line representing the margin. + * @private + */ + drawDottedLine_ : function() { + var rectangle = this.getVisibleLineCoordinates_(); + this.visibleLine.style.left = 100 * rectangle.x + '%'; + this.visibleLine.style.top = 100 * rectangle.y + '%'; + this.visibleLine.style.width = 100 * rectangle.width + '%'; + this.visibleLine.style.height = 100 * rectangle.height + '%'; + }, + + /** + * Draws the area the draggable area (not visible). + * @private + */ + drawDraggableArea_: function() { + var width = previewArea.pdfPlugin_.offsetWidth; + var height = previewArea.pdfPlugin_.offsetHeight; + + this.style.left = Math.round(this.rectangle.x * width) + 'px'; + this.style.top = Math.round(this.rectangle.y * height) + 'px'; + this.style.width = Math.round(this.rectangle.width * width) + 'px'; + this.style.height = Math.round(this.rectangle.height * height) + 'px'; + }, + + /** + * Calculates the coordinates and size of |this|. + * @param {print_preview.Rect} marginsRectangle A rectangle describing the + * selected margins values in percentages. + * @private + */ + getCoordinates_: function(marginsRectangle) { + var pageLocation = previewArea.getPageLocationNormalized(); + var totalWidth = previewArea.pdfPlugin_.offsetWidth; + var totalHeight = previewArea.pdfPlugin_.offsetHeight; + var offsetY = (MarginLine.CLICKABLE_REGION / 2) / totalHeight; + var offsetX = (MarginLine.CLICKABLE_REGION / 2) / totalWidth; + + if (this.isTop_()) { + var lineCoordinates = new print_preview.Rect( + pageLocation.x, + marginsRectangle.y - offsetY, + pageLocation.width, + MarginLine.CLICKABLE_REGION / totalHeight); + } else if (this.isBottom_()) { + var lineCoordinates = new print_preview.Rect( + pageLocation.x, + marginsRectangle.bottom - offsetY, + pageLocation.width, + MarginLine.CLICKABLE_REGION / totalHeight); + } else if (this.isRight_()) { + var lineCoordinates = new print_preview.Rect( + marginsRectangle.right - offsetX, + pageLocation.y, + MarginLine.CLICKABLE_REGION / totalWidth, + pageLocation.height); + } else if (this.isLeft_()) { + var lineCoordinates = new print_preview.Rect( + marginsRectangle.x - offsetX, + pageLocation.y, + MarginLine.CLICKABLE_REGION / totalWidth, + pageLocation.height); + } + return lineCoordinates; + }, + + /** + * Calculates the coordinates in percentages and size of the visible margin + * line, with respect to |this| div element. + * @return {print_preview.Rect} A rectangle describing the position of the + * visible line in percentages. + * @private + */ + getVisibleLineCoordinates_: function() { + if (this.isHorizontal_()) + var innerMarginsRect = new print_preview.Rect(0, 0.5, 1, 0); + else if (this.isVertical_()) + var innerMarginsRect = new print_preview.Rect(0.5, 0, 0, 1); + return innerMarginsRect; + }, + + /** + * @return {boolean} True if |this| refers to the top margin. + * @private + */ + isTop_: function() { + return this.marginGroup == print_preview.MarginSettings.TOP_GROUP; + }, + + /** + * @return {boolean} True if |this| refers to the bottom margin. + * @private + */ + isBottom_: function() { + return this.marginGroup == print_preview.MarginSettings.BOTTOM_GROUP; + }, + + /** + * @return {boolean} True if |this| refers to the left margin. + * @private + */ + isLeft_: function() { + return this.marginGroup == print_preview.MarginSettings.LEFT_GROUP; + }, + + /** + * @return {boolean} True if |this| refers to the bottom margin. + * @private + */ + isRight_: function() { + return this.marginGroup == print_preview.MarginSettings.RIGHT_GROUP; + }, + + /** + * @return {boolean} True if |this| is a horizontal line. + * @private + */ + isHorizontal_: function() { + return this.isTop_() || this.isBottom_() ; + }, + + /** + * @return {boolean} True if |this| is a vertical line. + * @private + */ + isVertical_: function() { + return this.isLeft_() || this.isRight_(); + }, + + }; + + return { + MarginLine: MarginLine + }; +}); diff --git a/chrome/browser/resources/print_preview/margin_settings.js b/chrome/browser/resources/print_preview/margin_settings.js index f9d81a3..5f48ed7 100644 --- a/chrome/browser/resources/print_preview/margin_settings.js +++ b/chrome/browser/resources/print_preview/margin_settings.js @@ -6,6 +6,107 @@ cr.define('print_preview', function() { 'use strict'; /** + * Creates a Margins object that holds four margin values. The units in which + * the values are expressed can be any numeric value. + * @constructor + * @param {number} left The left margin. + * @param {number} top The top margin. + * @param {number} right The right margin. + * @param {number} bottom The bottom margin. + */ + function Margins(left, top, right, bottom) { + this[MarginSettings.LEFT_GROUP] = left; + this[MarginSettings.TOP_GROUP] = top; + this[MarginSettings.RIGHT_GROUP] = right; + this[MarginSettings.BOTTOM_GROUP] = bottom; + } + + /** + * Rounds |value| keeping |precision| decimal numbers. Example: 32.76643 + * becomes 32.77. + * @param {number} value The number to round. + * @param {number} precision The desired precision. + * @return {number} The rounded number. + */ + Margins.roundToPrecision = function(value, precision) { + return Math.round(value * Math.pow(10, precision)) / + Math.pow(10, precision); + } + + Margins.prototype = { + /** + * Checks if |rhs| is equal to |this|. + * @param {Margins} rhs The Margins object to compare against. + * @return {boolean} true if they are equal. + */ + isEqual: function(rhs) { + return this[MarginSettings.TOP_GROUP] === rhs[MarginSettings.TOP_GROUP] && + this[MarginSettings.LEFT_GROUP] === rhs[MarginSettings.LEFT_GROUP] && + this[MarginSettings.RIGHT_GROUP] === + rhs[MarginSettings.RIGHT_GROUP] && + this[MarginSettings.BOTTOM_GROUP] === + rhs[MarginSettings.BOTTOM_GROUP]; + }, + + /** + * Copies the four margin values from |rhs|. + * @param {Margins} rhs The Margins object values to be used. + */ + copy: function(rhs) { + this[MarginSettings.TOP_GROUP] = rhs[MarginSettings.TOP_GROUP]; + this[MarginSettings.LEFT_GROUP] = rhs[MarginSettings.LEFT_GROUP]; + this[MarginSettings.RIGHT_GROUP] = rhs[MarginSettings.RIGHT_GROUP]; + this[MarginSettings.BOTTOM_GROUP] = rhs[MarginSettings.BOTTOM_GROUP]; + }, + + /** + * Converts |this| to inches and returns the result in a new Margins object. + * |this| is not affected. It assumes that |this| is currently expressed in + * points. + * @param {number} The number of decimal points to keep. + * @return {Margins} The equivalent of |this| in inches. + */ + toInches: function(precision) { + return new Margins( + Margins.roundToPrecision(convertPointsToInches( + this[MarginSettings.LEFT_GROUP]), precision), + Margins.roundToPrecision(convertPointsToInches( + this[MarginSettings.TOP_GROUP]), precision), + Margins.roundToPrecision(convertPointsToInches( + this[MarginSettings.RIGHT_GROUP]), precision), + Margins.roundToPrecision(convertPointsToInches( + this[MarginSettings.BOTTOM_GROUP]), precision) + ); + } + }; + + /** + * @constructor + * Class describing the layout of the page. + */ + function PageLayout(width, height, left, top, right, bottom) { + this.contentWidth_ = width; + this.contentHeight_ = height; + this.margins_ = new Margins(left, top, right, bottom); + } + + PageLayout.prototype = { + /** + * @type {number} The width of the page. + */ + get pageWidth() { + return this.margins_.left + this.margins_.right + this.contentWidth_; + }, + + /** + * @type {number} The height of the page. + */ + get pageHeight() { + return this.margins_.top + this.margins_.bottom + this.contentHeight_; + } + }; + + /** * Creates a MarginSettings object. This object encapsulates all settings and * logic related to the margins mode. * @constructor @@ -13,65 +114,130 @@ cr.define('print_preview', function() { function MarginSettings() { this.marginsOption_ = $('margins-option'); this.marginList_ = $('margin-list'); - // Holds the custom left margin value (if set). - this.customMarginLeft_ = -1; - // Holds the custom right margin value (if set). - this.customMarginRight_ = -1; - // Holds the custom top margin value (if set). - this.customMarginTop_ = -1; - // Holds the custom bottom margin value (if set). - this.customMarginBottom_ = -1; - // Margin list values. - this.customMarginsValue_ = 2; - this.defaultMarginsValue_ = 0; - this.noMarginsValue_ = 1; - // Default Margins option index. - this.defaultMarginsIndex_ = 0; + this.marginsUI_ = null; + + // Holds the custom margin values in points (if set). + this.customMargins_ = new Margins(-1, -1, -1, -1); + // Holds the previous custom margin values in points. + this.previousCustomMargins_ = new Margins(-1, -1, -1, -1); + // Holds the width of the page in points. + this.pageWidth_ = -1; + // Holds the height of the page in points. + this.pageHeight_ = -1; + // The last selected margin option. + this.lastSelectedOption_ = MarginSettings.MARGINS_VALUE_DEFAULT; + + // Holds the currently updated default page layout values. + this.currentDefaultPageLayout = null; + // Holds the default page layout values when the custom margins was last + // selected. + this.previousDefaultPageLayout_ = null; + + // True if the margins UI should be shown regardless of mouse position. + this.forceDisplayingMarginLines_ = true; } + // Number of points per inch. + MarginSettings.POINTS_PER_INCH = 72; + // Margin list values. + MarginSettings.MARGINS_VALUE_DEFAULT = 0; + MarginSettings.MARGINS_VALUE_NO_MARGINS = 1; + MarginSettings.MARGINS_VALUE_CUSTOM = 2; + // Default Margins option index. + MarginSettings.DEFAULT_MARGINS_OPTION_INDEX = 0; + // Group name corresponding to the top margin. + MarginSettings.TOP_GROUP = 'top'; + // Group name corresponding to the left margin. + MarginSettings.LEFT_GROUP = 'left'; + // Group name corresponding to the right margin. + MarginSettings.RIGHT_GROUP = 'right'; + // Group name corresponding to the bottom margin. + MarginSettings.BOTTOM_GROUP = 'bottom'; + cr.addSingletonGetter(MarginSettings); MarginSettings.prototype = { /** - * The selection list corresponding to the margins option. - * @return {HTMLInputElement} - */ - get marginList() { - return this.marginList_; - }, - - /** * Returns a dictionary of the four custom margin values. * @return {object} */ get customMargins() { - return {'marginLeft': this.customMarginLeft_, - 'marginTop': this.customMarginTop_, - 'marginRight': this.customMarginRight_, - 'marginBottom': this.customMarginBottom_}; + var margins = {}; + margins.marginLeft = this.customMargins_.left; + margins.marginTop = this.customMargins_.top; + margins.marginRight = this.customMargins_.right; + margins.marginBottom = this.customMargins_.bottom; + return margins; }, /** - * Gets the value of the selected margin option. + * @return {number} The value of the selected margin option. * @private - * @return {number} */ get selectedMarginsValue_() { return this.marginList_.options[this.marginList_.selectedIndex].value; }, /** - * Checks whether user has selected the Default Margins option or not. - * - * @return {boolean} true if default margins are selected. + * @return {boolean} True if default margins are selected. */ isDefaultMarginsSelected: function() { - return this.selectedMarginsValue_ == this.defaultMarginsValue_; + return this.selectedMarginsValue_ == MarginSettings.MARGINS_VALUE_DEFAULT; }, /** - * Adds listeners to all margin related controls. The listeners take care - * of altering their behavior depending on |hasPendingPreviewRequest|. + * @return {boolean} True if no margins are selected. + */ + isNoMarginsSelected: function() { + return this.selectedMarginsValue_ == + MarginSettings.MARGINS_VALUE_NO_MARGINS; + }, + + /** + * @return {boolean} True if custom margins are selected. + */ + isCustomMarginsSelected: function() { + return this.selectedMarginsValue_ == MarginSettings.MARGINS_VALUE_CUSTOM; + }, + + /** + * If the custom margin values have changed then request a new preview based + * on the newly set margins. + * @private + */ + requestPreviewIfNeeded_: function() { + if (!this.areMarginSettingsValid()) + return; + if (this.customMargins_.toInches(2).isEqual( + this.previousCustomMargins_.toInches(2))) { + return; + } + this.previousCustomMargins_.copy(this.customMargins_); + setDefaultValuesAndRegeneratePreview(false); + }, + + /** + * Listener executed when the mouse is over the sidebar. If the custom + * margin lines are displayed, then, it fades them out. + * @private + */ + onSidebarMouseOver_: function(e) { + if (!this.forceDisplayingMarginLines_) + this.marginsUI.hide(); + }, + + /** + * Listener executed when the mouse is over the main view. If the custom + * margin lines are hidden, then, it fades them in. + * @private + */ + onMainviewMouseOver_: function() { + this.forceDisplayingMarginLines_ = false; + this.marginsUI.show(); + }, + + /** + * Adds listeners to all margin related controls. */ addEventListeners: function() { this.marginList_.onchange = this.onMarginsChanged_.bind(this); @@ -79,34 +245,221 @@ cr.define('print_preview', function() { }, /** - * Listener executing when user selects a different margin option, ie, - * |this.marginList_| is changed. + * @return {boolean} True if the margin settings are valid. + */ + areMarginSettingsValid: function() { + if (this.marginsUI_ == null) + return true; + + var pairs = this.marginsUI.pairsAsList; + return pairs.every(function(pair) { return pair.box_.isValid; }); + }, + + /** + * Calculates the maximum allowable value of the selected margin text for + * every margin. + * @return {array} The maximum allowable value in order top, left, right, + * bottom. + * @private + */ + getMarginValueLimits_: function() { + var marginValueLimits = []; + marginValueLimits[0] = this.pageHeight_ - this.customMargins_.bottom; + marginValueLimits[1] = this.pageWidth_ - this.customMargins_.right; + marginValueLimits[2] = this.pageWidth_ - this.customMargins_.left; + marginValueLimits[3] = this.pageHeight_ - this.customMargins_.top; + return marginValueLimits; + }, + + /** + * When the user stops typing in the margin text box a new print preview is + * requested, only if + * 1) The input is compeletely valid (it can be parsed in its entirety). + * 2) The newly selected margins differ from the previously selected. + * @param {cr.Event} event The change event holding information about what + * changed. + * @private + */ + onMarginTextValueMayHaveChanged_: function(event) { + var marginBox = event.target; + var marginBoxValue = convertInchesToPoints(marginBox.margin); + this.customMargins_[marginBox.marginGroup] = marginBoxValue; + this.requestPreviewIfNeeded_(); + }, + + /** + * @type {print_preview.MarginsUI} The object holding the UI for specifying + * custom margins. + */ + get marginsUI() { + if (!this.marginsUI_) { + this.marginsUI_ = new print_preview.MarginsUI($('mainview')); + this.marginsUI_.addObserver( + this.onMarginTextValueMayHaveChanged_.bind(this)); + } + return this.marginsUI_; + }, + + /** + * Adds listeners when the custom margins option is selected. + * @private + */ + addCustomMarginEventListeners_: function() { + $('mainview').onmouseover = this.onMainviewMouseOver_.bind(this); + $('sidebar').onmouseover = this.onSidebarMouseOver_.bind(this); + }, + + /** + * Removes the event listeners associated with the custom margins option. + * @private + */ + removeCustomMarginEventListeners_: function() { + $('mainview').onmouseover = null; + $('sidebar').onmouseover = null; + this.marginsUI.hide(); + }, + + /** + * Updates |this.marginsUI| depending on the specified margins and the + * position of the page within the plugin. + * @private + */ + drawCustomMarginsUI_: function() { + // TODO(dpapad): find out why passing |!this.areMarginsSettingsValid()| + // directly produces the opposite value even though + // |this.getMarginsRectangleInPercent_()| and + // |this.getMarginValueLimits_()| have no side effects. + var keepDisplayedValue = !this.areMarginSettingsValid(); + this.marginsUI.update(this.getMarginsRectangleInPercent_(), + this.customMargins_, + this.getMarginValueLimits_(), + keepDisplayedValue); + this.marginsUI.draw(); + }, + + /** + * Called when there is change in the preview position or size. + */ + onPreviewPositionChanged: function() { + if (this.isCustomMarginsSelected() && previewArea.pdfLoaded && + pageSettings.totalPageCount != undefined) { + this.drawCustomMarginsUI_(); + } + }, + + /** + * Executes when user selects a different margin option, ie, + * |this.marginList_.selectedIndex| is changed. * @private */ onMarginsChanged_: function() { - if (this.selectedMarginsValue_ == this.defaultMarginsValue_) { - setDefaultValuesAndRegeneratePreview(false); - } else if (this.selectedMarginsValue_ == this.noMarginsValue_) { - this.customMarginLeft_ = 0; - this.customMarginTop_ = 0; - this.customMarginRight_ = 0; - this.customMarginBottom_ = 0; - setDefaultValuesAndRegeneratePreview(false); + if (this.isDefaultMarginsSelected()) + this.onDefaultMarginsSelected_(); + else if (this.isNoMarginsSelected()) + this.onNoMarginsSelected_(); + else if (this.isCustomMarginsSelected()) + this.onCustomMarginsSelected_(); + + this.lastSelectedOption_ = this.selectedMarginsValue_; + }, + + /** + * Executes when the default margins option is selected. + * @private + */ + onDefaultMarginsSelected_: function() { + this.removeCustomMarginEventListeners_(); + this.forceDisplayingMarginLines_ = true; + setDefaultValuesAndRegeneratePreview(false); + }, + + /** + * Executes when the no margins option is selected. + * @private + */ + onNoMarginsSelected_: function() { + this.removeCustomMarginEventListeners_(); + this.forceDisplayingMarginLines_ = true; + this.customMargins_ = new Margins(0, 0, 0, 0); + setDefaultValuesAndRegeneratePreview(false); + }, + + /** + * Executes when the custom margins option is selected. + * @private + */ + onCustomMarginsSelected_: function() { + this.addCustomMarginEventListeners_(); + + if (this.lastSelectedOption_ == MarginSettings.MARGINS_VALUE_DEFAULT) + this.customMargins_ = this.currentDefaultPageLayout.margins_; + this.previousCustomMargins_.copy(this.customMargins_); + + if (this.previousDefaultPageLayout_ != this.currentDefaultPageLayout) { + this.pageWidth_ = this.currentDefaultPageLayout.pageWidth; + this.pageHeight_ = this.currentDefaultPageLayout.pageHeight; } - // TODO(aayushkumar): Add handler for custom margins + + this.previousDefaultPageLayout_ = this.currentDefaultPageLayout; + this.drawCustomMarginsUI_(); + this.marginsUI.show(); + }, + + /** + * Calculates the coordinates of the four margin lines. These are the + * coordinates where the margin lines should be displayed. The coordinates + * are expressed in terms of percentages with respect to the total width + * and height of the plugin. + * @return {print_preview.Rect} A rectnangle that describes the position of + * the four margin lines. + * @private + */ + getMarginsRectangleInPercent_: function() { + var pageLocation = previewArea.getPageLocationNormalized(); + var marginsInPercent = this.getMarginsInPercent_(); + var leftX = pageLocation.x + marginsInPercent.left; + var topY = pageLocation.y + marginsInPercent.top; + var contentWidth = pageLocation.width - (marginsInPercent.left + + marginsInPercent.right); + var contentHeight = pageLocation.height - (marginsInPercent.top + + marginsInPercent.bottom); + return new print_preview.Rect( + leftX, topY, contentWidth, contentHeight); + }, + + /** + * @return {print_preview.Margins} The currently selected margin values + * normalized to the total width and height of the plugin. + * @private + */ + getMarginsInPercent_: function() { + var pageInformation = previewArea.getPageLocationNormalized(); + var totalWidthInPoints = this.pageWidth_ / pageInformation.width; + var totalHeightInPoints = this.pageHeight_ / pageInformation.height; + var marginsInPercent = new Margins( + this.customMargins_.left / totalWidthInPoints, + this.customMargins_.top / totalHeightInPoints, + this.customMargins_.right / totalWidthInPoints, + this.customMargins_.bottom / totalHeightInPoints); + return marginsInPercent; }, /** * If custom margins is the currently selected option then change to the * default margins option. + * @private */ resetMarginsIfNeeded: function() { - if (this.selectedMarginsValue_ == this.customMarginsValue_) - this.marginList_.options[this.defaultMarginsIndex_].selected = true; + if (this.isCustomMarginsSelected()) { + this.marginList_.options[ + MarginSettings.DEFAULT_MARGINS_OPTION_INDEX].selected = true; + this.removeCustomMarginEventListeners_(); + this.lastSelectedOption_ = MarginSettings.MARGINS_VALUE_DEFAULT; + } }, /** - * Listener executing when a PDFLoaded event occurs. + * Executes when a PDFLoaded event occurs. * @private */ onPDFLoaded_: function() { @@ -117,5 +470,6 @@ cr.define('print_preview', function() { return { MarginSettings: MarginSettings, + PageLayout: PageLayout, }; }); diff --git a/chrome/browser/resources/print_preview/margin_textbox.js b/chrome/browser/resources/print_preview/margin_textbox.js new file mode 100644 index 0000000..5034bbf --- /dev/null +++ b/chrome/browser/resources/print_preview/margin_textbox.js @@ -0,0 +1,282 @@ +// Copyright (c) 2011 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. + +cr.define('print_preview', function() { + 'strict'; + + function MarginTextbox(groupName) { + var box = document.createElement('input'); + box.__proto__ = MarginTextbox.prototype; + box.setAttribute('type', 'text'); + box.className = MarginTextbox.CSS_CLASS_MARGIN_TEXTBOX; + box.value = '0'; + + // @type {string} Specifies which margin this line refers to. + box.marginGroup = groupName; + // @type {boolean} True if the displayed value is valid. + box.isValid = true; + // @type {number} Timer used to detect when the user stops typing. + box.timerId_ = null; + // @type {number} The last valid value in points. + box.lastValidValueInPoints = 0; + // @type {print_preview.Rect} A rectangle describing the four margins. + box.marginsRectangle_ = null; + // @type {number} The upper allowed limit for the corresponding margin. + box.valueLimit = null; + + box.addEventListeners_(); + return box; + } + + MarginTextbox.CSS_CLASS_MARGIN_TEXTBOX = 'margin-box'; + MarginTextbox.MARGIN_BOX_HEIGHT = 15; + MarginTextbox.MARGIN_BOX_VERTICAL_PADDING = 5; + MarginTextbox.MARGIN_BOX_WIDTH = 40; + MarginTextbox.MARGIN_BOX_HORIZONTAL_PADDING = 10; + + // Keycode for the "Escape" key. + MarginTextbox.ESCAPE_KEYCODE = 27; + // Keycode for the "Enter" key. + MarginTextbox.ENTER_KEYCODE = 13; + + MarginTextbox.convertPointsToInchesText = function(toConvert) { + var inInches = convertPointsToInches(toConvert); + return MarginTextbox.convertInchesToInchesText(inInches); + }; + + MarginTextbox.convertInchesToInchesText = function(toConvert) { + return toConvert.toFixed(2) + '"'; + }; + + /** + * @return {number} The total height of a margin textbox (including padding). + */ + MarginTextbox.totalHeight = function() { + return MarginTextbox.MARGIN_BOX_HEIGHT + + 2 * MarginTextbox.MARGIN_BOX_VERTICAL_PADDING; + } + + /** + * @return {number} The total width of a margin textbox (including padding). + */ + MarginTextbox.totalWidth = function() { + return MarginTextbox.MARGIN_BOX_WIDTH + + 2 * MarginTextbox.MARGIN_BOX_HORIZONTAL_PADDING; + } + + MarginTextbox.prototype = { + __proto__: HTMLInputElement.prototype, + + /** + * Updates the state of |this|. + * @param {print_preview.Rect} marginsRectangle A rectangle describing the + * margins in percentages. + * @param {number} value The margin value in points. + * @param {number} valueLimit The upper allowed value for the margin. + * @param {boolean} keepDisplayedValue True if the currently displayed value + * should not be updated. + */ + update: function(marginsRectangle, value, valueLimit, keepDisplayedValue) { + this.marginsRectangle_ = marginsRectangle; + this.lastValidValueInPoints = value; + if (!keepDisplayedValue) { + this.value = MarginTextbox.convertPointsToInchesText( + this.lastValidValueInPoints); + } + + this.valueLimit = valueLimit; + this.validate(); + }, + + get margin() { + return print_preview.extractMarginValue(this.value); + }, + + /** + * Updates |this.isValid|. + */ + validate: function() { + this.isValid = print_preview.isMarginTextValid(this.value, + this.valueLimit); + if (this.isValid) + this.value = MarginTextbox.convertInchesToInchesText(this.margin); + }, + + /** + * Updates the background color depending on |isValid| by adding/removing + * the appropriate CSS class. + * @param {boolean} isValid True if the margin is valid. + */ + updateColor: function() { + this.isValid ? this.classList.remove('invalid') : + this.classList.add('invalid'); + }, + + /** + * Draws this textbox. + */ + draw: function() { + var topLeft = this.getCoordinates_(); + var totalWidth = previewArea.pdfPlugin_.offsetWidth; + var totalHeight = previewArea.pdfPlugin_.offsetHeight; + + this.style.left = Math.round(topLeft.x * totalWidth) + 'px'; + this.style.top = Math.round(topLeft.y * totalHeight) + 'px'; + this.updateColor(); + }, + + /** + * @return {boolean} True if |this| refers to the top margin. + * @private + */ + isTop_: function() { + return this.marginGroup == print_preview.MarginSettings.TOP_GROUP; + }, + + /** + * @return {boolean} True if |this| refers to the bottom margin. + * @private + */ + isBottom_: function() { + return this.marginGroup == print_preview.MarginSettings.BOTTOM_GROUP; + }, + + /** + * @return {boolean} True if |this| refers to the left margin. + * @private + */ + isLeft_: function() { + return this.marginGroup == print_preview.MarginSettings.LEFT_GROUP; + }, + + /** + * @return {boolean} True if |this| refers to the bottom margin. + * @private + */ + isRight_: function() { + return this.marginGroup == print_preview.MarginSettings.RIGHT_GROUP; + }, + + /** + * Calculates the coordinates where |this| should be displayed. + * @return {{x: number, y: number}} The coordinates (in percent) where + * |this| should be drawn relative to the upper left corner of the + * plugin. + * @private + */ + getCoordinates_: function() { + var x = 0, y = 0; + var totalWidth = previewArea.pdfPlugin_.offsetWidth; + var totalHeight = previewArea.pdfPlugin_.offsetHeight; + var offsetY = (MarginTextbox.totalHeight() / 2) / totalHeight; + var offsetX = (MarginTextbox.totalWidth() / 2) / totalWidth; + + if (this.isTop_()) { + x = this.marginsRectangle_.middleX - offsetX; + y = this.marginsRectangle_.y; + } else if (this.isBottom_()) { + x = this.marginsRectangle_.middleX - offsetX; + y = this.marginsRectangle_.bottom - 2 * offsetY; + } else if (this.isRight_()) { + x = this.marginsRectangle_.right - 2 * offsetX; + y = this.marginsRectangle_.middleY - offsetY; + } else if (this.isLeft_()) { + x = this.marginsRectangle_.x; + y = this.marginsRectangle_.middleY - offsetY; + } + + return { x: x, y: y }; + }, + + /** + * Adds event listeners for various events. + * @private + */ + addEventListeners_: function() { + this.oninput = this.resetTimer_.bind(this); + this.onblur = this.onBlur_.bind(this); + this.onkeypress = this.onKeyPressed_.bind(this); + this.onkeyup = this.onKeyUp_.bind(this); + }, + + /** + * Executes whenever a blur event occurs. + * @private + */ + onBlur_: function() { + clearTimeout(this.timerId_); + this.validate(); + if (!this.isValid) { + this.value = MarginTextbox.convertPointsToInchesText( + this.lastValidValueInPoints); + this.validate(); + } + + this.updateColor(); + cr.dispatchSimpleEvent(document, 'updateSummary'); + cr.dispatchSimpleEvent(document, 'updatePrintButton'); + cr.dispatchSimpleEvent(this, 'MarginsMayHaveChanged'); + }, + + /** + * Executes whenever a keypressed event occurs. Note: Only the "Enter" key + * event is handled. The "Escape" key does not result in such event, + * therefore it is handled by |this.onKeyUp_|. + * @param {KeyboardEvent} e The event that triggered this listener. + * @private + */ + onKeyPressed_: function(e) { + if (e.keyCode == MarginTextbox.ENTER_KEYCODE) + this.blur(); + }, + + /** + * Executes whenever a keyup event occurs. Note: Only the "Escape" + * key event is handled. + * @param {KeyboardEvent} e The event that triggered this listener. + * @private + */ + onKeyUp_: function(e) { + if (e.keyCode == MarginTextbox.ESCAPE_KEYCODE) { + this.value = MarginTextbox.convertPointsToInchesText( + this.lastValidValueInPoints); + this.validate(); + this.updateColor(); + cr.dispatchSimpleEvent(document, 'updateSummary'); + cr.dispatchSimpleEvent(document, 'updatePrintButton'); + } + }, + + /** + * Resetting the timer used to detect when the user stops typing in order + * to update the print preview. + * @private + */ + resetTimer_: function() { + clearTimeout(this.timerId_); + this.timerId_ = window.setTimeout( + this.onTextValueMayHaveChanged_.bind(this), 500); + }, + + /** + * Executes whenever the user stops typing. + * @private + */ + onTextValueMayHaveChanged_: function() { + this.validate(); + this.updateColor(); + cr.dispatchSimpleEvent(document, 'updateSummary'); + cr.dispatchSimpleEvent(document, 'updatePrintButton'); + + if (!this.isValid) + return; + cr.dispatchSimpleEvent(this, 'MarginsMayHaveChanged'); + } + + }; + + return { + MarginTextbox: MarginTextbox + }; +}); diff --git a/chrome/browser/resources/print_preview/margin_utils.js b/chrome/browser/resources/print_preview/margin_utils.js new file mode 100644 index 0000000..73a925a --- /dev/null +++ b/chrome/browser/resources/print_preview/margin_utils.js @@ -0,0 +1,87 @@ +// Copyright (c) 2011 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. + +cr.define('print_preview', function() { + 'use strict'; + + /** + * Checks if |text| has a valid margin value format. A valid format is + * parsable as a number and is greater than zero. + * Example: "1.00", "1", ".5", "1.1" are valid values. + * Example: "1.4dsf", "-1" are invalid. + * Note: The inch symbol (") at the end of |text| is allowed. + * + * @param {string} text The text to check. + * @return {number} The margin value represented by |text| or null if |text| + * does not represent a valid number. + */ + function extractMarginValue(text) { + // Remove whitespace anywhere in the string. + text.replace(/\s*/g, ''); + if (text.length == 0) + return -1; + // Remove the inch(") symbol at end of string if present. + if (text.charAt(text.length - 1) == '\"') + text = text.slice(0, text.length - 1); + var regex = /^\d*(\.\d+)?$/ + if (regex.test(text)) + return parseFloat(text); + return -1; + } + + /** + * @param {sting} text The text to check (in inches). + * @param {number} limit The upper bound of the valid margin range (in + * points). + * @return {boolean} True of |text| can be parsed and it is within the allowed + * range. + */ + function isMarginTextValid(text, limit) { + var value = extractMarginValue(text); + if (value == -1) + return false; + value = convertInchesToPoints(value); + return value <= limit; + } + + /** + * Creates a Rect object. This object describes a rectangle in a 2D plane. The + * units of |x|, |y|, |width|, |height| are chosen by clients of this class. + * @constructor + */ + function Rect(x, y, width, height) { + // @type {number} Horizontal distance of the upper left corner from origin. + this.x = x; + // @type {number} Vertical distance of the upper left corner from origin. + this.y = y; + // @type {number} Width of |this| rectangle. + this.width = width; + // @type {number} Height of |this| rectangle. + this.height = height; + }; + + Rect.prototype = { + get right() { + return this.x + this.width; + }, + + get bottom() { + return this.y + this.height; + }, + + get middleX() { + return this.x + this.width / 2; + }, + + get middleY() { + return this.y + this.height / 2; + } + }; + + return { + extractMarginValue: extractMarginValue, + isMarginTextValid: isMarginTextValid, + Rect: Rect, + }; +}); diff --git a/chrome/browser/resources/print_preview/margins_ui.js b/chrome/browser/resources/print_preview/margins_ui.js new file mode 100644 index 0000000..443f8fd --- /dev/null +++ b/chrome/browser/resources/print_preview/margins_ui.js @@ -0,0 +1,136 @@ +// Copyright (c) 2011 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. + +cr.define('print_preview', function() { + 'strict'; + + /** + * @constructor + * This class represents a margin line and a textbox corresponding to that + * margin. + */ + function MarginsUIPair(groupName) { + this.line_ = new print_preview.MarginLine(groupName); + this.box_ = new print_preview.MarginTextbox(groupName); + } + + MarginsUIPair.prototype = { + __proto__: MarginsUIPair.prototype, + + /** + * Updates the state. + */ + update: function(marginsRectangle, value, valueLimit, keepDisplayedValue) { + this.line_.update(marginsRectangle); + this.box_.update(marginsRectangle, value, valueLimit, keepDisplayedValue); + }, + + /** + * Draws |this| based on the state. + */ + draw: function() { + this.line_.draw(); + this.box_.draw(); + } + }; + + function MarginsUI(parentNode) { + var marginsUI = document.createElement('div'); + marginsUI.__proto__ = MarginsUI.prototype; + marginsUI.id = 'customized-margins'; + + marginsUI.topPair_ = new MarginsUIPair( + print_preview.MarginSettings.TOP_GROUP); + marginsUI.leftPair_ = new MarginsUIPair( + print_preview.MarginSettings.LEFT_GROUP); + marginsUI.rightPair_ = new MarginsUIPair( + print_preview.MarginSettings.RIGHT_GROUP); + marginsUI.bottomPair_ = new MarginsUIPair( + print_preview.MarginSettings.BOTTOM_GROUP); + parentNode.appendChild(marginsUI); + + var uiPairs = marginsUI.pairsAsList; + for (var i = 0; i < uiPairs.length; i++) { + marginsUI.appendChild(uiPairs[i].line_); + marginsUI.appendChild(uiPairs[i].box_); + } + return marginsUI; + } + + MarginsUI.prototype = { + __proto__: HTMLDivElement.prototype, + + /** + * Adds an observer for |MarginsMayHaveChanged| event. + * @param {function} func A callback function to be called when + * |MarginsMayHaveChanged| event occurs. + */ + addObserver: function(func) { + var uiPairs = this.pairsAsList; + for (var i = 0; i < uiPairs.length; i++) + uiPairs[i].box_.addEventListener('MarginsMayHaveChanged', func); + }, + + /** + * @return {array} An array including all |MarginUIPair| objects. + */ + get pairsAsList() { + return [this.topPair_, this.leftPair_, this.rightPair_, this.bottomPair_]; + }, + + /** + * Updates the state of the margins UI. + * @param {print_preview.Rect} + * @param {Margins} marginValues + * @param {array} valueLimits + */ + update: function(marginsRectangle, marginValues, valueLimits, + keepDisplayedValue) { + var uiPairs = this.pairsAsList; + var order = ['top', 'left', 'right', 'bottom']; + for (var i = 0; i < uiPairs.length; i++) { + uiPairs[i].update(marginsRectangle, + marginValues[order[i]], + valueLimits[i], + keepDisplayedValue); + } + }, + + /** + * Draws |this| based on the latest state. + */ + draw: function() { + this.applyClippingMask_(); + this.pairsAsList.forEach(function(pair) { pair.draw(); }); + }, + + /** + * Shows the margins UI. + */ + show: function() { + this.hidden = false; + }, + + /** + * Hides the margins UI. + */ + hide: function() { + this.hidden = true; + }, + + /** + * Applies a clipping mask on |this| so that it does not paint on top of the + * scrollbars (if any). + */ + applyClippingMask_: function() { + var bottom = previewArea.height; + var right = previewArea.width; + this.style.clip = "rect(0, " + right + "px, " + bottom + "px, 0)"; + } + }; + + return { + MarginsUI: MarginsUI + }; +}); diff --git a/chrome/browser/resources/print_preview/preview_area.js b/chrome/browser/resources/print_preview/preview_area.js new file mode 100644 index 0000000..8a970a2 --- /dev/null +++ b/chrome/browser/resources/print_preview/preview_area.js @@ -0,0 +1,136 @@ +// Copyright (c) 2011 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. + +cr.define('print_preview', function() { + 'strict'; + + /** + * Creates a PreviewArea object. It represents the area where the preview + * document is displayed. + * @constructor + */ + function PreviewArea() { + // The embedded pdf plugin object. + this.pdfPlugin_ = null; + + // True if the pdf document is loaded in the preview area. + this.pdfLoaded_ = false; + + // Contains the zoom level just before a new preview is requested so the + // same zoom level can be restored. + this.zoomLevel_ = null; + // @type {{x: number, y: number}} Contains the page offset values just + // before a new preview is requested so that the scroll amount can be + // restored later. + this.pageOffset_ = null; + } + + cr.addSingletonGetter(PreviewArea); + + PreviewArea.prototype = { + /** + * The width of the plugin area in pixels, excluding any visible scrollbars, + * @type {number} + */ + get width() { + return this.widthPercent * this.pdfPlugin_.offsetWidth; + }, + + /** + * The height of the plugin area in pixels, excluding any visible + * scrollbars. + * @type {number} + */ + get height() { + return this.heightPercent * this.pdfPlugin_.offsetHeight; + }, + + /** + * The width of the plugin area in percent, excluding any visible + * scrollbars. + * @type {number} + */ + get widthPercent() { + var width = this.pdfPlugin_.getWidth(); + var scrollbarWidth = this.pdfPlugin_.getVerticalScrollbarThickness(); + return (width - scrollbarWidth) / width; + }, + + /** + * The height of the plugin area in percent, excluding any visible + * scrollbars. + * @type {number} + */ + get heightPercent() { + var height = this.pdfPlugin_.getHeight(); + var scrollbarHeight = this.pdfPlugin_.getHorizontalScrollbarThickness(); + return (height - scrollbarHeight) / height; + }, + + get pdfLoaded() { + return this.pdfLoaded_; + }, + + set pdfLoaded(pdfLoaded) { + this.pdfLoaded_ = pdfLoaded; + }, + + /** + * @return {print_preview.Rect} A rectangle describing the postion of the + * most visible page normalized with respect to the total height and width + * of the plugin. + */ + getPageLocationNormalized: function() { + var pluginLocation = + this.pdfPlugin_.getPageLocationNormalized().split(';'); + return new print_preview.Rect(parseFloat(pluginLocation[0]), + parseFloat(pluginLocation[1]), + parseFloat(pluginLocation[2]), + parseFloat(pluginLocation[3])); + }, + + /** + * Resets the state variables of |this|. + */ + resetState: function() { + if (this.pdfPlugin_) { + this.zoomLevel_ = this.pdfPlugin_.getZoomLevel(); + this.pageOffset_ = { + x: this.pdfPlugin_.pageXOffset(), + y: this.pdfPlugin_.pageYOffset() + }; + } + this.pdfLoaded_ = false; + }, + + /** + * Adds event listeners for various events. + * @private + */ + addEventListeners: function() { + document.addEventListener('PDFLoaded', + this.onPDFLoaded_.bind(this)); + }, + + /** + * Listener executing when a PDFLoaded event occurs. + * @private + */ + onPDFLoaded_: function() { + this.pdfPlugin_ = $('pdf-viewer'); + this.pdfLoaded_ = true; + if (this.zoomLevel_ != null && this.pageOffset_ != null) { + this.pdfPlugin_.setZoomLevel(this.zoomLevel_); + this.pdfPlugin_.setPageXOffset(this.pageOffset_.x); + this.pdfPlugin_.setPageYOffset(this.pageOffset_.y); + } else { + this.pdfPlugin_.fitToHeight(); + } + } + }; + + return { + PreviewArea: PreviewArea, + }; +}); diff --git a/chrome/browser/resources/print_preview/print_header.js b/chrome/browser/resources/print_preview/print_header.js index 76fbdab..92bf086 100644 --- a/chrome/browser/resources/print_preview/print_header.js +++ b/chrome/browser/resources/print_preview/print_header.js @@ -100,6 +100,11 @@ cr.define('print_preview', function() { return; } + if (!marginSettings.areMarginSettingsValid()) { + this.summary_.innerHTML = ''; + return; + } + var pageSet = pageSettings.selectedPagesSet; var numOfSheets = pageSet.length; var summaryLabel = diff --git a/chrome/browser/resources/print_preview/print_preview.css b/chrome/browser/resources/print_preview/print_preview.css index 69fd060..1808f63 100644 --- a/chrome/browser/resources/print_preview/print_preview.css +++ b/chrome/browser/resources/print_preview/print_preview.css @@ -722,6 +722,45 @@ select { pointer-events: none; } +input[type='text'].margin-box { + background-color: #2a2a2a; + color: #fff; + cursor: auto; + font-family: arial; + font-size: 10px; + height: 15px; + padding: 5px 10px; + position: absolute; + text-align: center; + width: 40px; + z-index: 3; +} + +input[type='text'].margin-box.invalid { + background-color: #c11b17; +} + +.draggable-area { + background-color: transparent; + border-color: transparent; + pointer-events: none; + position: absolute; + z-index: 2; +} + +.margin-line { + border-color: #4080FA; + border-style: dashed; + border-width: 1px; + position: absolute; + z-index: 2; +} + +#customized-margins { + position: absolute; + top: 0; +} + #messages { color: #404040; font-size: 13px; diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html index 083c60d..83b5757 100644 --- a/chrome/browser/resources/print_preview/print_preview.html +++ b/chrome/browser/resources/print_preview/print_preview.html @@ -38,10 +38,8 @@ <hr> <include src="color_settings.html"></include> <hr> - <div id="display-margin-options" hidden> - <include src="margin_settings.html"></include> - <hr> - </div> + <include src="margin_settings.html"></include> + <hr> <include src="header_footer_settings.html"></include> <hr> <div id="system-dialog-div"> diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index 55f212d..c3bfbca 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js @@ -53,27 +53,32 @@ var isPrintReadyMetafileReady = false; // True when preview tab is hidden. var isTabHidden = false; -// Object holding the print and cancel buttons. +// @type {print_preview.PrintHeader} Holds the print and cancel buttons. var printHeader; -// Object holding all the pages related settings. +// @type {print_preview.PageSettings} Holds all the pages related settings. var pageSettings; -// Object holding all the copies related settings. +// @type {print_preview.CopiesSettings} Holds all the copies related settings. var copiesSettings; -// Object holding all the layout related settings. +// @type {print_preview.LayoutSettings} Holds all the layout related settings. var layoutSettings; -// Object holding all the margin related settings. +// @type {print_preview.MarginSettings} Holds all the margin related settings. var marginSettings; -// Object holding all the header footer related settings. +// @type {print_preview.HeaderFooterSettings} Holds all the header footer +// related settings. var headerFooterSettings; -// Object holding all the color related settings. +// @type {print_preview.ColorSettings} Holds all the color related settings. var colorSettings; +// @type {print_preview.PreviewArea} Holds information related to the preview +// area (on the right). +var previewArea; + // True if the user has click 'Advanced...' in order to open the system print // dialog. var showingSystemDialog = false; @@ -130,12 +135,14 @@ function onLoad() { marginSettings = print_preview.MarginSettings.getInstance(); headerFooterSettings = print_preview.HeaderFooterSettings.getInstance(); colorSettings = print_preview.ColorSettings.getInstance(); + previewArea = print_preview.PreviewArea.getInstance(); pageSettings.addEventListeners(); copiesSettings.addEventListeners(); headerFooterSettings.addEventListeners(); layoutSettings.addEventListeners(); marginSettings.addEventListeners(); colorSettings.addEventListeners(); + previewArea.addEventListeners(); $('printer-list').onchange = updateControlsWithSelectedPrinterCapabilities; showLoadingAnimation(); @@ -321,8 +328,8 @@ function finishedCloudPrinting() { function areSettingsValid() { var selectedPrinter = getSelectedPrinterName(); return pageSettings.isPageSelectionValid() && - (copiesSettings.isValid() || - selectedPrinter == PRINT_TO_PDF || + marginSettings.areMarginSettingsValid() && + (copiesSettings.isValid() || selectedPrinter == PRINT_TO_PDF || selectedPrinter == PRINT_WITH_CLOUD_PRINT); } @@ -504,6 +511,7 @@ function requestPrintPreview() { printSettings.save(); layoutSettings.updateState(); + previewArea.resetState(); isPrintReadyMetafileReady = false; isFirstPageLoaded = false; @@ -762,7 +770,6 @@ function onPDFLoad() { if (previewModifiable) { setPluginPreviewPageCount(); } - $('pdf-viewer').fitToHeight(); cr.dispatchSimpleEvent(document, 'PDFLoaded'); isFirstPageLoaded = true; checkAndHideOverlayLayerIfValid(); @@ -794,8 +801,18 @@ function onDidGetPreviewPageCount(pageCount, isModifiable, previewResponseId) { cr.dispatchSimpleEvent(document, 'updateSummary'); } +/** + * @param {printing::PageSizeMargins} pageLayout The default layout of the page + * in points. + */ function onDidGetDefaultPageLayout(pageLayout) { - // TODO(aayushkumar): Do something here! + marginSettings.currentDefaultPageLayout = new print_preview.PageLayout( + pageLayout.contentWidth, + pageLayout.contentHeight, + pageLayout.marginLeft, + pageLayout.marginTop, + pageLayout.marginRight, + pageLayout.marginBottom); } /** @@ -971,21 +988,48 @@ function createPDFPlugin(srcDataIndex) { pdfViewer.setAttribute('aria-atomic', 'true'); $('mainview').appendChild(pdfViewer); pdfViewer.onload('onPDFLoad()'); + pdfViewer.onScroll('onPreviewPositionChanged()'); + pdfViewer.onPluginSizeChanged('onPreviewPositionChanged()'); pdfViewer.removePrintButton(); pdfViewer.grayscale(true); } /** + * Called either when there is a scroll event or when the plugin size changes. + */ +function onPreviewPositionChanged() { + marginSettings.onPreviewPositionChanged(); +} + +/** * @return {boolean} true if a compatible pdf plugin exists. */ function checkCompatiblePluginExists() { - var dummyPlugin = $('dummy-viewer') - return !!(dummyPlugin.onload && - dummyPlugin.goToPage && - dummyPlugin.removePrintButton && - dummyPlugin.loadPreviewPage && - dummyPlugin.printPreviewPageCount && - dummyPlugin.resetPrintPreviewUrl); + var dummyPlugin = $('dummy-viewer'); + var pluginInterface = [ dummyPlugin.onload, + dummyPlugin.goToPage, + dummyPlugin.removePrintButton, + dummyPlugin.loadPreviewPage, + dummyPlugin.printPreviewPageCount, + dummyPlugin.resetPrintPreviewUrl, + dummyPlugin.onPluginSizeChanged, + dummyPlugin.onScroll, + dummyPlugin.pageXOffset, + dummyPlugin.pageYOffset, + dummyPlugin.setZoomLevel, + dummyPlugin.setPageXOffset, + dummyPlugin.setPageYOffset, + dummyPlugin.getHorizontalScrollbarThickness, + dummyPlugin.getVerticalScrollbarThickness, + dummyPlugin.getPageLocationNormalized, + dummyPlugin.getHeight, + dummyPlugin.getWidth ]; + + for (var i = 0; i < pluginInterface.length; i++) { + if (!pluginInterface[i]) + return false; + } + return true; } /** @@ -1063,3 +1107,8 @@ window.onkeydown = onKeyDown; <include src="layout_settings.js"/> <include src="color_settings.js"/> <include src="margin_settings.js"/> +<include src="margin_textbox.js"/> +<include src="margin_line.js"/> +<include src="margin_utils.js"/> +<include src="margins_ui.js"/> +<include src="preview_area.js"/> diff --git a/chrome/browser/resources/print_preview/print_preview_utils.js b/chrome/browser/resources/print_preview/print_preview_utils.js index 594769e..90ecd16 100644 --- a/chrome/browser/resources/print_preview/print_preview_utils.js +++ b/chrome/browser/resources/print_preview/print_preview_utils.js @@ -203,3 +203,24 @@ function randomInteger(endPointA, endPointB) { to = Math.max(endPointA, endPointB); return Math.floor(Math.random() * (to - from + 1) + from); } + +// Number of points per inch. +POINTS_PER_INCH = 72; + +/** + * Converts |value| from inches to points. + * @param {number} value The number in inches. + * @return {number} |value| in points. + */ +function convertInchesToPoints(value) { + return value * POINTS_PER_INCH; +} + +/** + * Converts |value| from points to inches. + * @param {number} value The number in points. + * @return {number} |value| in inches. + */ +function convertPointsToInches(value) { + return value / POINTS_PER_INCH; +} diff --git a/chrome/browser/resources/print_preview/print_preview_utils_test.html b/chrome/browser/resources/print_preview/print_preview_utils_test.html index 58994ed..c633954 100644 --- a/chrome/browser/resources/print_preview/print_preview_utils_test.html +++ b/chrome/browser/resources/print_preview/print_preview_utils_test.html @@ -105,6 +105,18 @@ function testPageSetToPageRanges() { assertEquals(pageRanges[2].to, 11); } +function testConvertInchesToPoints() { + assertEquals(convertInchesToPoints(1), 72); + assertEquals(convertInchesToPoints(2), 144); + assertEquals(convertInchesToPoints(0.45), 32.4); +} + +function testConvertPointsToInches() { + assertEquals(convertPointsToInches(72), 1); + assertEquals(convertPointsToInches(144), 2); + assertEquals(convertPointsToInches(32.4), 0.45); +} + </script> </body> </html> |