Index: chrome/browser/resources/print_preview/previewarea/custom_margins.js |
diff --git a/chrome/browser/resources/print_preview/previewarea/custom_margins.js b/chrome/browser/resources/print_preview/previewarea/custom_margins.js |
new file mode 100644 |
index 0000000000000000000000000000000000000000..04afa20ce7cdebc2d57dae99e1e7a0bb08cd82b3 |
--- /dev/null |
+++ b/chrome/browser/resources/print_preview/previewarea/custom_margins.js |
@@ -0,0 +1,513 @@ |
+// 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. |
+ |
+cr.define('print_preview', function() { |
+ 'use strict'; |
+ |
+ /** |
+ * UI component used for setting custom print margins. |
+ * |
+ * @param {!print_preview.PrintTicketStore} printTicketStore Used to read and |
+ * write custom margin values. |
+ * @constructor |
+ * @extends {print_preview.Component} |
+ */ |
+ function CustomMargins(printTicketStore) { |
+ print_preview.Component.call(this); |
+ |
+ /** |
+ * Used to read and write custom margin values. |
+ * @type {!print_preview.PrintTicketStore} |
+ * @private |
+ */ |
+ this.printTicketStore_ = printTicketStore; |
+ |
+ /** |
+ * Convenience array that contains all of the margin controls. |
+ * @type {!Array<!print_preview.MarginControl>} |
+ * @private |
+ */ |
+ this.controls_ = {}; |
+ for (var orientation in print_preview.MarginControl.Orientation) { |
+ orientation = print_preview.MarginControl.Orientation[orientation]; |
+ var control = new print_preview.MarginControl(orientation); |
+ this.controls_[orientation] = control; |
+ this.addChild(control); |
+ } |
+ |
+ /** |
+ * Margin control currently being dragged. Null if no control is being |
+ * dragged. |
+ * @type {print_preview.MarginControl} |
+ * @private |
+ */ |
+ this.draggedControl_ = null; |
+ |
+ /** |
+ * Translation transformation in pixels to translate from the origin of the |
+ * custom margins component to the top-left corner of the most visible |
+ * preview page. |
+ * @type {!print_preview.Coordinate2d} |
+ * @private |
+ */ |
+ this.translateTransform_ = new print_preview.Coordinate2d(0, 0); |
+ |
+ /** |
+ * Scaling transformation to scale from pixels to the units which the |
+ * print preview is in. The scaling factor is the same in both dimensions, |
+ * so this field is just a single number. |
+ * @type {number} |
+ * @private |
+ */ |
+ this.scaleTransform_ = 1; |
+ }; |
+ |
+ /** |
+ * CSS classes used by the custom margins component. |
+ * @enum {string} |
+ * @private |
+ */ |
+ CustomMargins.Classes_ = { |
+ DRAGGING_HORIZONTAL: 'custom-margins-dragging-horizontal', |
+ DRAGGING_VERTICAL: 'custom-margins-dragging-vertical' |
+ }; |
+ |
+ /** |
+ * Minimum distance in points between two margins. |
+ * @type {number} |
+ * @const |
+ * @private |
+ */ |
+ CustomMargins.MINIMUM_MARGINS_DISTANCE_ = 72; |
+ |
+ CustomMargins.prototype = { |
+ __proto__: print_preview.Component.prototype, |
+ |
+ updateBoundingBox: function(boundingBox) { |
+ this.boundingBox_ = boundingBox; |
+ // TODO Update UI |
+ }, |
+ |
+ /** |
+ * Updates the translation transformation that translates pixel values in |
+ * the space of the HTML DOM. |
+ * @param {print_preview.Coordinate2d} translateTransform Updated value of |
+ * the translation transformation. |
+ */ |
+ updateTranslationTransform: function(translateTransform) { |
+ if (!translateTransform.equals(this.translateTransform_)) { |
+ this.translateTransform_ = translateTransform; |
+ for (var orientation in this.controls_) { |
+ this.controls_[orientation].translateTransform = translateTransform; |
+ } |
+ } |
+ }, |
+ |
+ updateScaleTransform: function(scaleTransform) { |
+ if (scaleTransform != this.scaleTransform_) { |
+ this.scaleTransform_ = scaleTransform; |
+ for (var orientation in this.controls_) { |
+ this.controls_[orientation].scaleTransform = scaleTransform; |
+ } |
+ } |
+ }, |
+ |
+ /** @override */ |
+ decorateInternal: function() { |
+ for (var orientation in this.controls_) { |
+ this.controls_[orientation].render(this.getElement()); |
+ } |
+ }, |
+ |
+ /** @override */ |
+ enterDocument: function() { |
+ print_preview.Component.prototype.enterDocument.call(this); |
+ this.tracker.add( |
+ this.getElement(), 'mousemove', this.onMouseMove_.bind(this)); |
+ this.tracker.add( |
+ this.getElement(), 'mouseup', this.onMouseUp_.bind(this)); |
+ this.tracker.add( |
+ this.getElement(), 'mouseover', this.onMouseOver_.bind(this)); |
+ this.tracker.add( |
+ this.getElement(), 'mouseout', this.onMouseOut_.bind(this)); |
+ |
+ this.tracker.add( |
+ this.printTicketStore_, |
+ print_preview.PrintTicketStore.Event.INITIALIZE, |
+ this.onTicketInitialize_.bind(this)); |
+ this.tracker.add( |
+ this.printTicketStore_, |
+ print_preview.PrintTicketStore.Event.TICKET_CHANGE, |
+ this.onTicketChange_.bind(this)); |
+ this.tracker.add( |
+ this.printTicketStore_, |
+ print_preview.PrintTicketStore.Event.DOCUMENT_CHANGE, |
+ this.onDocumentChange_.bind(this)); |
+ this.tracker.add( |
+ this.printTicketStore_, |
+ print_preview.PrintTicketStore.Event.CAPABILITIES_CHANGE, |
+ this.onCapabilitiesChange_.bind(this)); |
+ |
+ for (var orientation in this.controls_) { |
+ var control = this.controls_[orientation]; |
+ this.tracker.add( |
+ control, |
+ print_preview.MarginControl.Event.DRAG_START, |
+ this.onControlDragStart_.bind(this, control)); |
+ this.tracker.add( |
+ control, |
+ print_preview.MarginControl.Event.TEXT_CHANGE, |
+ this.updatePrintTicket_.bind(this, control)); |
+ } |
+ }, |
+ |
+ setIsMarginControlsVisible_: function(isVisible) { |
+ for (var orientation in this.controls_) { |
+ this.controls_[orientation].isVisible = isVisible; |
+ } |
+ }, |
+ |
+ moveControlWithinConstraints_: function(control, position) { |
+ var orientationEnum = print_preview.MarginControl.Orientation; |
+ |
+ // Get desired position |
+ var newPosInPts; |
+ var isTopOrBottom = control.orientation == orientationEnum.TOP || |
+ control.orientation == orientationEnum.BOTTOM; |
+ if (isTopOrBottom) { |
+ newPosInPts = control.convertPixelsToPts(position.y); |
+ } else { |
+ newPosInPts = control.convertPixelsToPts(position.x); |
+ } |
+ |
+ // Apply constraints between controls |
+ var constraintControl; |
+ if (control.orientation == orientationEnum.TOP) { |
+ constraintControl = this.controls_[orientationEnum.BOTTOM]; |
+ } else if (control.orientation == orientationEnum.RIGHT) { |
+ constraintControl = this.controls_[orientationEnum.LEFT]; |
+ } else if (control.orientation == orientationEnum.BOTTOM) { |
+ constraintControl = this.controls_[orientationEnum.TOP]; |
+ } else { |
+ constraintControl = this.controls_[orientationEnum.RIGHT]; |
+ } |
+ var sum = constraintControl.positionInPts + newPosInPts + |
+ CustomMargins.MINIMUM_MARGINS_DISTANCE_; |
+ if (isTopOrBottom && sum > this.printTicketStore_.pageSize.height) { |
+ newPosInPts = this.printTicketStore_.pageSize.height - |
+ CustomMargins.MINIMUM_MARGINS_DISTANCE_ - |
+ constraintControl.positionInPts; |
+ } |
+ if (!isTopOrBottom && sum > this.printTicketStore_.pageSize.width) { |
+ newPosInPts = this.printTicketStore_.pageSize.width - |
+ CustomMargins.MINIMUM_MARGINS_DISTANCE_ - |
+ constraintControl.positionInPts; |
+ } |
+ |
+ // Make sure margin is above minimum |
+ var minimum; |
+ if (control.orientation == orientationEnum.TOP) { |
+ minimum = this.printTicketStore_.printableArea.origin.y; |
+ } else if (control.orientation == orientationEnum.RIGHT) { |
+ minimum = this.printTicketStore_.pageSize.width - |
+ this.printTicketStore_.printableArea.origin.x - |
+ this.printTicketStore_.printableArea.size.width; |
+ } else if (control.orientation == orientationEnum.BOTTOM) { |
+ minimum = this.printTicketStore_.pageSize.height - |
+ this.printTicketStore_.printableArea.origin.y - |
+ this.printTicketStore_.printableArea.size.height; |
+ } else { |
+ minimum = this.printTicketStore_.printableArea.origin.x; |
+ } |
+ newPosInPts = Math.max(minimum, newPosInPts); |
+ |
+ // Set new position |
+ control.positionInPts = newPosInPts; |
+ }, |
+ |
+ updatePrintTicket_: function(control) { |
+ var orientationEnum = print_preview.MarginControl.Orientation; |
+ var oldMargins = this.printTicketStore_.getCustomMargins(); |
+ var top = control.orientation == orientationEnum.TOP ? |
+ control.positionInPts : oldMargins.top; |
+ var right = control.orientation == orientationEnum.RIGHT ? |
+ control.positionInPts : oldMargins.right; |
+ var bottom = control.orientation == orientationEnum.BOTTOM ? |
+ control.positionInPts : oldMargins.bottom; |
+ var left = control.orientation == orientationEnum.LEFT ? |
+ control.positionInPts : oldMargins.left; |
+ this.printTicketStore_.updateCustomMargins( |
+ new print_preview.Margins(top, right, bottom, left)); |
+ }, |
+ |
+ /** |
+ * Called when a margin control starts to drag. |
+ * @param {print_preview.MarginControl} control The control which started to |
+ * drag. |
+ * @private |
+ */ |
+ onControlDragStart_: function(control) { |
+ this.draggedControl_ = control; |
+ var isControlTopOrBottom = |
+ control.orientation == print_preview.MarginControl.Orientation.TOP || |
+ control.orientation == print_preview.MarginControl.Orientation.BOTTOM; |
+ this.getElement().classList.add( |
+ isControlTopOrBottom ? |
+ CustomMargins.Classes_.DRAGGING_VERTICAL : |
+ CustomMargins.Classes_.DRAGGING_HORIZONTAL); |
+ }, |
+ |
+ /** |
+ * Called when the mouse moves in the custom margins component. Moves the |
+ * dragged margin control. |
+ * @param {MouseEvent} evt Contains the position of the mouse. |
+ * @private |
+ */ |
+ onMouseMove_: function(evt) { |
+ if (this.draggedControl_) { |
+ this.moveControlWithinConstraints_( |
+ this.draggedControl_, |
+ this.draggedControl_.translateMouseToPositionInPixels( |
+ new print_preview.Coordinate2d(evt.x, evt.y))); |
+ } |
+ }, |
+ |
+ /** |
+ * Called when the mouse is released in the custom margins component. |
+ * Releases the dragged margin control. |
+ * @param {MouseEvent} evt Contains the position of the mouse. |
+ * @private |
+ */ |
+ onMouseUp_: function(evt) { |
+ if (this.draggedControl_) { |
+ this.getElement().classList.remove( |
+ CustomMargins.Classes_.DRAGGING_VERTICAL); |
+ this.getElement().classList.remove( |
+ CustomMargins.Classes_.DRAGGING_HORIZONTAL); |
+ this.moveControlWithinConstraints_( |
+ this.draggedControl_, |
+ this.draggedControl_.translateMouseToPositionInPixels( |
+ new print_preview.Coordinate2d(evt.x, evt.y))); |
+ this.updatePrintTicket_(this.draggedControl_); |
+ this.draggedControl_ = null; |
+ } |
+ }, |
+ |
+ /** |
+ * Called when the mouse moves onto the component. Shows the margin |
+ * controls. |
+ * @private |
+ */ |
+ onMouseOver_: function() { |
+ if (this.printTicketStore_.isInitialized && |
+ this.printTicketStore_.getMarginsType() == |
+ print_preview.Margins.Type.CUSTOM) { |
+ this.setIsMarginControlsVisible_(true); |
+ } |
+ }, |
+ |
+ /** |
+ * Called when the mouse moves off of the component. Hides the margin |
+ * controls. |
+ * @private |
+ */ |
+ onMouseOut_: function() { |
+ var isAnyControlInFocus = false; |
+ for (var orientation in this.controls_) { |
+ if (this.controls_[orientation].isInFocus) { |
+ isAnyControlInFocus = true; |
+ break; |
+ } |
+ } |
+ if (!isAnyControlInFocus) { |
+ this.setIsMarginControlsVisible_(false); |
+ } |
+ }, |
+ |
+ /** |
+ * Called when the print ticket is initialized. Creates and updates the |
+ * margin controls. |
+ * @private |
+ */ |
+ onTicketInitialize_: function() { |
+ for (var orientation in this.controls_) { |
+ this.controls_[orientation].measurementSystem = |
+ this.printTicketStore_.measurementSystem; |
+ this.controls_[orientation].pageSize = this.printTicketStore_.pageSize; |
+ } |
+ this.onTicketChange_(); |
+ }, |
+ |
+ /** |
+ * Called when the print ticket changes. Updates the position of the margin |
+ * controls. |
+ * @private |
+ */ |
+ onTicketChange_: function() { |
+ var marginsType = this.printTicketStore_.getMarginsType(); |
+ var margins = this.printTicketStore_.getCustomMargins(); |
+ if (marginsType == print_preview.Margins.Type.CUSTOM && margins != null) { |
+ var orientEnum = print_preview.MarginControl.Orientation; |
+ this.controls_[orientEnum.TOP].positionInPts = margins.top; |
+ this.controls_[orientEnum.RIGHT].positionInPts = margins.right; |
+ this.controls_[orientEnum.BOTTOM].positionInPts = margins.bottom; |
+ this.controls_[orientEnum.LEFT].positionInPts = margins.left; |
+ } |
+ this.setIsMarginControlsVisible_( |
+ marginsType == print_preview.Margins.Type.CUSTOM); |
+ }, |
+ |
+ /** |
+ * Called when the document changes. Updates margin controls if the page |
+ * size has changed. |
+ * @private |
+ */ |
+ onDocumentChange_: function() { |
+ for (var orientation in this.controls_) { |
+ this.controls_[orientation].pageSize = this.printTicketStore_.pageSize; |
+ } |
+ }, |
+ |
+ /** |
+ * Called when the destination print capabilities have changed. Shows or |
+ * hides the custom margins. |
+ * @private |
+ */ |
+ onCapabilitiesChange_: function() { |
+ if (!this.printTicketStore_.hasMarginsCapability() || |
+ this.printTicketStore_.getMarginsType() != |
+ print_preview.Margins.Type.CUSTOM) { |
+ this.setIsMarginControlsVisible_(false); |
+ } |
+ }, |
+ |
+ /** |
+ * 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)'; |
+ }, |
+ |
+ /** |
+ * 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. |
+ previewArea.update(); |
+ var keepDisplayedValue = !this.areMarginSettingsValid(); |
+ this.marginsUI.update(this.getMarginsRectangleInPercent_(), |
+ this.customMargins_, |
+ this.getMarginValueLimits_(), |
+ keepDisplayedValue, |
+ this.getMarginValueLimitsInPercent_()); |
+ this.marginsUI.draw(); |
+ }, |
+ |
+ /** |
+ * Executes when user selects a different margin option, ie, |
+ * |this.select_.selectedIndex| is changed. |
+ * @private |
+ */ |
+ onMarginsChanged_: function() { |
+ if (this.isDefaultMarginsSelected() || this.isMinimumMarginsSelected() || |
+ this.isNoMarginsSelected()) |
+ this.onDefaultMinimumNoMarginsSelected_(); |
+ else if (this.isCustomMarginsSelected()) |
+ this.onCustomMarginsSelected_(); |
+ }, |
+ |
+ /** |
+ * 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.pageLocationNormalized; |
+ 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() { |
+ return this.convertMarginsInPointsToPercent(this.customMargins_); |
+ }, |
+ |
+ /** |
+ * Converts |marginsToConvert| to points and normalizes it to the height and |
+ * width of the plugin. |
+ * @return {print_preview.Margins} The margins in percent. |
+ * @private |
+ */ |
+ convertMarginsInPointsToPercent: function(marginsToConvert) { |
+ var pageInformation = previewArea.pageLocationNormalized; |
+ var totalWidthInPoints = this.pageWidth_ / pageInformation.width; |
+ var totalHeightInPoints = this.pageHeight_ / pageInformation.height; |
+ var marginsInPercent = new Margins( |
+ marginsToConvert.left / totalWidthInPoints, |
+ marginsToConvert.top / totalHeightInPoints, |
+ marginsToConvert.right / totalWidthInPoints, |
+ marginsToConvert.bottom / totalHeightInPoints); |
+ return marginsInPercent; |
+ }, |
+ |
+ /** |
+ * Executes when a |customEvents.PDF_LOADED| event occurs. |
+ * @private |
+ */ |
+ onPDFLoaded_: function() { |
+ if (!previewModifiable) { |
+ fadeOutOption(this.marginsOption_); |
+ return; |
+ } |
+ |
+ if (this.forceMarginsUIOnPDFLoad_) { |
+ this.updatePageData_(); |
+ this.drawCustomMarginsUI_(); |
+ this.addCustomMarginEventListeners_(); |
+ this.marginsUI.show(); |
+ this.forceMarginsUIOnPDFLoad_ = false; |
+ } |
+ }, |
+ |
+ /** |
+ * Updates |this.customMargins_|, |this.pageWidth_|, |this.pageHeight_|. |
+ * @private |
+ */ |
+ updatePageData_: function() { |
+ if (!this.customMargins_) |
+ this.customMargins_ = this.currentDefaultPageLayout.margins_.clone(); |
+ |
+ this.pageWidth_ = this.currentDefaultPageLayout.pageWidth; |
+ this.pageHeight_ = this.currentDefaultPageLayout.pageHeight; |
+ } |
+ }; |
+ |
+ // Export |
+ return { |
+ CustomMargins: CustomMargins |
+ }; |
+}); |