Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4997)

Unified Diff: chrome/browser/resources/print_preview/margin_settings.js

Issue 7891016: Print Preview: Adding UI for margin settings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing causing a regeneration because of rounding error. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/print_preview/margin_settings.js
diff --git a/chrome/browser/resources/print_preview/margin_settings.js b/chrome/browser/resources/print_preview/margin_settings.js
index f9d81a3053927d16cfb72ae8662cbff1d0e08e9f..a6ef9165e42d381dda341f75ba8c56c20c98715e 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,225 @@ 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;
+ for (var i = 0; i < pairs.length; i++) {
Evan Stade 2011/10/07 03:29:58 return pairs.every(function(pair) { return pair.
dpapad 2011/10/07 16:49:20 Done.
+ if (!pairs[i].box_.isValid)
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * 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).
Evan Stade 2011/10/07 03:29:58 indent the list
dpapad 2011/10/07 16:49:20 Done.
+ * 2) The newly selected margins differ from the previous selected margins.
+ * @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.
+ * @private
Evan Stade 2011/10/07 03:29:58 .
dpapad 2011/10/07 16:49:20 ?
+ * @return {print_preview.Rect} A rectnangle that describes the position of
+ * the four margin lines.
+ */
+ 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);
+ },
+
+ /**
+ * @private
Evan Stade 2011/10/07 03:29:58 .
dpapad 2011/10/07 16:49:20 ?
+ * @return {print_preview.Margins} The currently selected margin values
+ * normalized to the total width and height of the plugin.
+ */
+ 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 +474,6 @@ cr.define('print_preview', function() {
return {
MarginSettings: MarginSettings,
+ PageLayout: PageLayout,
};
});

Powered by Google App Engine
This is Rietveld 408576698