Chromium Code Reviews| Index: chrome/browser/resources/print_preview/data/print_ticket_store.js |
| diff --git a/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chrome/browser/resources/print_preview/data/print_ticket_store.js |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..67bc86f82371395a5d3255edb01dd42ead80cc6a |
| --- /dev/null |
| +++ b/chrome/browser/resources/print_preview/data/print_ticket_store.js |
| @@ -0,0 +1,608 @@ |
| +// 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. |
| + |
| +// TODO Optimize this to not dispatch CHANGE events when nothing really changed. |
| + |
| +cr.define('print_preview', function() { |
| + 'use strict'; |
| + |
| + /** |
| + * Storage of the print ticket and document statistics. |
| + * |
| + * Dispatches events when the contents of the print ticket or document |
| + * statistics change. Also handles validation of the print ticket against |
| + * destination capabilities and against the document. |
| + * |
| + * @constructor |
| + * @extends {cr.EventTarget} |
| + */ |
| + function PrintTicketStore() { |
| + cr.EventTarget.call(this); |
| + |
| + /** |
| + * Information about the document to print. |
| + * @type {DocumentInfo} |
| + * @private |
| + */ |
| + this.documentInfo_ = new DocumentInfo(); |
| + |
| + /** |
| + * Printing capabilities of Chromium and the currently selected destination. |
| + * @type {print_preview.ChromiumCapabilities} |
| + * @private |
| + */ |
| + this.capabilities_ = null; |
| + |
| + /** |
| + * Print ticket information. Used to print and generate previews. |
| + * @type {print_preview.ChromiumPrintTicket} |
| + * @private |
| + */ |
| + this.ticket_ = null; |
| + |
| + /** |
| + * Current measurement system. Used to work with margin measurements. |
| + * @type {print_preview.MeasurementSystem} |
| + * @private |
| + */ |
| + this.measurementSystem_ = null; |
| + |
| + /** |
| + * Cached page number set. Used to not have to parse page range string |
| + * everytime its requested. |
| + * @type {print_preview.PageNumberSet} |
| + * @private |
| + */ |
| + this.pageNumberSet_ = null; |
| + }; |
| + |
| + /** |
| + * Events dispatched by the print ticket store. |
| + * @enum {string} |
| + */ |
| + PrintTicketStore.Event = { |
| + CAPABILITIES_CHANGE: 'print_preview.PrintTicketStore.CAPABILITIES_CHANGE', |
| + DOCUMENT_CHANGE: 'print_preview.PrintTicketStore.DOCUMENT_CHANGE', |
| + INITIALIZE: 'print_preview.PrintTicketStore.INITIALIZE', |
| + TICKET_CHANGE: 'print_preview.PrintTicketStore.TICKET_CHANGE' |
| + }; |
| + |
| + /** |
| + * Minimum size in points the margins need to be to fit a header or footer. |
| + * TODO: Figure out someway to actually calculate this value. |
| + * @type {number} |
| + * @const |
| + * @private |
| + */ |
| + PrintTicketStore.MINIMUM_HEADER_FOOTER_HEIGHT_ = 0; |
| + |
| + PrintTicketStore.prototype = { |
| + __proto__: cr.EventTarget.prototype, |
| + |
| + /** @override */ |
| + dispatchEvent: function(evt) { |
| + // TODO REMOVE ME |
| + log(evt.type); |
| + cr.EventTarget.prototype.dispatchEvent.call(this, evt); |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether the print ticket store has been initialized. |
| + */ |
| + get isInitialized() { |
| + return !!this.ticket_; |
| + }, |
| + |
| + /** @return {boolean} Whether the document is modifiable. */ |
| + get isDocumentModifiable() { |
| + return this.documentInfo_.isModifiable; |
| + }, |
| + |
| + /** @return {number} Number of pages in the document. */ |
| + get pageCount() { |
| + return this.documentInfo_.pageCount; |
| + }, |
| + |
| + /** |
| + * @param {number} pageCount New number of pages in the document. |
| + * Dispatches a DOCUMENT_CHANGE event if the value changes. |
| + */ |
| + updatePageCount: function(pageCount) { |
| + if (this.documentInfo_.pageCount != pageCount) { |
| + this.documentInfo_.pageCount = pageCount; |
| + this.pageNumberSet_ = null; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); |
| + } |
| + }, |
| + |
| + /** |
| + * @return {!print_preview.PrintableArea} Printable area of the document in |
| + * points. |
| + */ |
| + get printableArea() { |
| + return this.documentInfo_.printableArea; |
| + }, |
| + |
| + /** |
| + * @param {!print_preview.PrintableArea} printableArea New printable area of |
| + * the document in points. Dispatches a DOCUMENT_CHANGE event if the |
| + * value changes. |
| + */ |
| + updatePrintableArea: function(printableArea) { |
| + if (!this.documentInfo_.printableArea.equals(printableArea)) { |
| + log('PrintableArea: ' + printableArea.origin.x + ' ' + |
| + printableArea.origin.y + ' ' + printableArea.size.width + ' ' + |
| + printableArea.size.height); |
| + this.documentInfo_.printableArea = printableArea; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {!print_preview.Size} Size of the document in points. */ |
| + get pageSize() { |
| + return this.documentInfo_.pageSize; |
| + }, |
| + |
| + /** |
| + * @param {!print_preview.Size} pageSize New size of the document. |
| + * Dispatches a DOCUMENT_CHANGE event if the value changes. |
| + */ |
| + updatePageSize: function(pageSize) { |
| + if (!this.documentInfo_.pageSize.equals(pageSize)) { |
| + log('Updating page size to: ' + pageSize.width + ' ' + pageSize.height); |
| + this.documentInfo_.pageSize = pageSize; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); |
| + } |
| + }, |
| + |
| + /** |
| + * @return {!print_preview.MeasurementSystem} Measurement system of the |
| + * local system. |
| + */ |
| + get measurementSystem() { |
| + if (!this.isInitialized) { |
| + throw Error( |
| + 'Trying to get measurement system before ticket is initialized'); |
| + } |
| + return /** @type {!print_preview.MeasurementSystem} */ (this. |
| + measurementSystem_); |
| + }, |
| + |
| + /** |
| + * Initializes the print ticket store. Dispatches an INITIALIZE event. |
| + * @param {boolean} isDocumentModifiable Whether the document to print is |
| + * modifiable (i.e. can be re-flowed by Chromium). |
| + * @param {boolean} isDuplexEnabled Previous duplex setting. |
| + * @param {boolean} isHeaderFooterEnabled Previous header-footer setting. |
| + * @param {print_preview.Margins.Type} marginsType Previous margins type. |
| + * @param {print_preview.Margins} customMargins Initial custom margins. |
| + * @param {!print_preview.MeasurementSystem} measurementSystem Measurement |
| + * system of the local system. |
| + */ |
| + initialize: function( |
| + isDocumentModifiable, |
| + isDuplexEnabled, |
| + isHeaderFooterEnabled, |
| + marginsType, |
| + customMargins, |
| + measurementSystem) { |
| + |
| + this.documentInfo_.isModifiable = isDocumentModifiable; |
| + |
| + // Create capabilities that can be handled by Chromium before any |
| + // particular print destination is selected. |
| + this.capabilities_ = new print_preview.ChromiumCapabilities( |
| + true /*hasCopiesCapability*/, |
| + '1' /*defaultCopiesStr*/, |
| + true /*hasCollateCapability*/, |
| + true /*defaultIsCollateEnabled*/, |
| + true /*hasDuplexCapability*/, |
| + true /*defaultIsDuplexEnabled*/, |
| + true /*hasOrientationCapability*/, |
| + false /*defaultIsLandscapeEnabled*/, |
| + true /*hasColorCapability*/, |
| + true /*defaultIsColorEnabled*/); |
| + |
| + // Initialize ticket with user's previous values. |
| + this.ticket_ = new print_preview.ChromiumPrintTicket(this.capabilities_); |
| + this.ticket_.isDuplexEnabled = isDuplexEnabled; |
| + this.ticket_.marginsType = marginsType; |
| + this.ticket_.customMargins = customMargins; |
| + this.ticket_.isHeaderFooterEnabled = isHeaderFooterEnabled; |
| + |
| + // Initialize measurement system. |
| + this.measurementSystem_ = measurementSystem; |
| + |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.INITIALIZE); |
| + }, |
| + |
| + /** |
| + * Updates the capabilities of the destination the print ticket is for. |
| + * Dispatches a CAPABILITIES_CHANGE event. |
| + * @param {!print_preview.ChromiumCapabilities} caps New capabilities. |
| + */ |
| + updateDestinationCapabilities: function(caps) { |
| + this.capabilities_ = caps; |
| + this.ticket_.capabilities = caps; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.CAPABILITIES_CHANGE); |
| + }, |
| + |
| + /** @return {boolean} Whether the ticket store has the copies capability. */ |
| + hasCopiesCapability: function() { |
| + return this.capabilities_.hasCopiesCapability; |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether the string representation of the copies value |
| + * currently in the ticket store is valid. |
| + */ |
| + isCopiesValid: function() { |
| + return this.isCopiesValidForValue(this.ticket_.copiesStr); |
| + }, |
| + |
| + /** |
| + * @param {string} value String representation of the number of print |
| + * copies. |
| + * @return {boolean} Whether the given value is valid--an integer in the |
| + * range [1, 999]. |
| + */ |
| + isCopiesValidForValue: function(value) { |
| + if (/[^\d]+/.test(value)) { |
| + return false; |
| + } |
| + var copies = parseInt(value); |
| + if (copies > 999 || copies < 1) { |
| + return false; |
| + } |
| + return true; |
| + }, |
| + |
| + /** @return {number} Number of copies to print. */ |
| + getCopies: function() { |
| + return parseInt(this.ticket_.copiesStr); |
| + }, |
| + |
| + /** |
| + * @return {string} String representation of the number of copies to print. |
| + */ |
| + getCopiesStr: function() { |
| + return this.ticket_.copiesStr; |
| + }, |
| + |
| + /** |
| + * Updates the string representation of the number of copies to print. |
| + * Dispatches a TICKET_CHANGE event if the string value has changed. |
| + * @param {string} New string representation of the number of copies to |
| + * print. |
| + */ |
| + updateCopies: function(copies) { |
| + if (!this.hasCopiesCapability()) { |
| + throw Error( |
| + 'Updating copies capability but destination does not have a ' + |
| + 'copies capability'); |
| + } |
| + if (this.ticket_.copiesStr != copies) { |
| + this.ticket_.copiesStr = copies; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {boolean} Whether the ticket store has a collate capability. */ |
| + hasCollateCapability: function() { |
| + return this.capabilities_.hasCollateCapability; |
| + }, |
| + |
| + /** @return {boolean} Whether collate is enabled. */ |
| + isCollateEnabled: function() { |
| + return this.ticket_.isCollateEnabled; |
| + }, |
| + |
| + /** |
| + * Updates whether collate is enabled. Dispatches a TICKET_CHANGE event if |
| + * collate has changed. |
| + * @param {boolean} isCollate Whether collate is enabled. |
| + */ |
| + updateCollate: function(isCollate) { |
| + if (!this.hasCollateCapability()) { |
| + throw Error( |
| + 'Updating collate capability but destination does not have a ' + |
| + 'collate capability'); |
| + } |
| + if (this.ticket_.isCollateEnabled != isCollate) { |
| + this.ticket_.isCollateEnabled = isCollate; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether the ticket store has color printing capability. |
| + */ |
| + hasColorCapability: function() { |
| + return this.capabilities_.hasColorCapability; |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether color printing is enabled. |
| + */ |
| + isColorEnabled: function() { |
| + return this.ticket_.isColorEnabled; |
| + }, |
| + |
| + /** |
| + * Updates whether color printing is enabled. Dispatches a TICKET_CHANGE if |
| + * color has changed. |
| + * @param {boolean} isColor Whether the color printing is enabled. |
| + */ |
| + updateColor: function(isColor) { |
| + if (!this.hasColorCapability()) { |
| + throw Error( |
| + 'Updating color capability but destination does not have a color ' + |
| + 'capability'); |
| + } |
| + if (this.ticket_.isColorEnabled != isColor) { |
| + this.ticket_.isColorEnabled = isColor; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {boolean} Whether the header-footer capability is available. */ |
| + hasHeaderFooterCapability: function() { |
| + // Checks the printable area and updates the visibility of header footer |
| + // option based on the selected margins. |
| + if (!this.documentInfo_.isModifiable || |
| + this.ticket_.marginsType == print_preview.Margins.Type.NO_MARGINS) { |
| + return false; |
| + } |
| + if (this.ticket_.marginsType == print_preview.Margins.Type.CUSTOM) { |
| + var margins = this.ticket_.customMargins; |
| + // TODO This condition only checks if the margin is non-zero. It should |
| + // check whether the margin is large enough to render the header-footer. |
| + var availableTopMargin = this.documentInfo_.printableArea.origin.y - |
| + PrintTicketStore.MINIMUM_HEADER_FOOTER_HEIGHT_; |
| + var availbleBottomMargin = this.documentInfo_.pageSize.height - |
| + this.documentInfo_.printableArea.origin.y - |
| + this.documentInfo_.printableArea.size.height - |
| + PrintTicketStore.MINIMUM_HEADER_FOOTER_HEIGHT_; |
| + if (margins.top < availableTopMargin || |
| + margins.bottom < availbleBottomMargin) { |
| + return false; |
| + } |
| + } |
| + return true; |
| + }, |
| + |
| + /** @return {boolean} Whether the header-footer setting is enabled. */ |
| + isHeaderFooterEnabled: function() { |
| + return this.ticket_.isHeaderFooterEnabled; |
| + }, |
| + |
| + /** |
| + * Updates the whether the header-footer setting is enabled. Dispatches a |
| + * TICKET_CHANGE event if the setting changed. |
| + * @param {boolean} isHeaderFooterEnabled Whether the header-footer setting |
| + * is enabled. |
| + */ |
| + updateHeaderFooter: function(isHeaderFooterEnabled) { |
| + if (!this.hasHeaderFooterCapability()) { |
| + throw Error( |
| + 'Updating header-footer capability but destination does not have ' + |
| + 'a header-footer capability'); |
| + } |
| + if (this.ticket_.isHeaderFooterEnabled != isHeaderFooterEnabled) { |
| + this.ticket_.isHeaderFooterEnabled = isHeaderFooterEnabled; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether the page orientation capability is available. |
| + */ |
| + hasOrientationCapability: function() { |
| + // TODO Technically, the print destination can still change the |
| + // orientation of the print out (at least for cloud printers). But the |
| + // preview wouldn't update in the case where the document is not |
| + // modifiable so this is a bad user experience. |
| + return this.documentInfo_.isModifiable; |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether the document should be printed in landscape. |
| + */ |
| + isLandscapeEnabled: function() { |
| + return this.ticket_.isLandscapeEnabled; |
| + }, |
| + |
| + /** |
| + * Updates whether the document should be printed in landscape. Dispatches |
| + * a TICKET_CHANGE event if the setting changes. |
| + * @param {boolean} isLandscape Whether the document should be printed in |
| + * landscape. |
| + */ |
| + updateOrientation: function(isLandscape) { |
| + if (!this.hasOrientationCapability()) { |
| + throw Error( |
| + 'Updating orientation capability but destination does not have ' + |
| + 'an orientation capability'); |
| + } |
| + if (this.ticket_.isLandscapeEnabled != isLandscape) { |
| + this.ticket_.isLandscapeEnabled = isLandscape; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {boolean} Whether the duplexing capability is available. */ |
| + hasDuplexCapability: function() { |
| + return this.capabilities_.hasDuplexCapability; |
| + }, |
| + |
| + /** @return {boolean} Whether the document should be printed in duplex. */ |
| + isDuplexEnabled: function() { |
| + return this.ticket_.isDuplexEnabled; |
| + }, |
| + |
| + /** |
| + * Updates the duplexing setting. Dispatches a TICKET_CHANGE event if the |
| + * value changes. |
| + * @param {boolean} isDuplex Whether the document should be printed in |
| + * duplex. |
| + */ |
| + updateDuplex: function(isDuplex) { |
| + if (!this.hasDuplexCapability()) { |
| + throw Error( |
| + 'Updating duplex capability but destination does not have a ' + |
| + 'duplex capability'); |
| + } |
| + if (this.ticket_.isDuplexEnabled != isDuplex) { |
| + this.ticket_.isDuplexEnabled = isDuplex; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {boolean} Whether the margins capability is available. */ |
| + hasMarginsCapability: function() { |
| + return this.documentInfo_.isModifiable; |
| + }, |
| + |
| + /** @return {print_preview.Margins.Type} Type of predefined margins. */ |
| + getMarginsType: function() { |
| + return this.ticket_.marginsType; |
| + }, |
| + |
| + /** |
| + * Updates the type of predefined margins. Dispatches a TICKET_CHANGE event |
| + * if the margins type changes. |
| + * @param {print_preview.Margins.Type} marginsType Type of predefined |
| + * margins. |
| + */ |
| + updateMarginsType: function(marginsType) { |
| + if (!this.hasMarginsCapability()) { |
| + throw Error( |
| + 'Updating margins capability but destination does not have a ' + |
| + 'margin capability'); |
| + } |
| + if (this.ticket_.marginsType != marginsType) { |
| + this.ticket_.marginsType = marginsType; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {print_preview.Margins} Custom margins of the document. */ |
| + getCustomMargins: function() { |
| + return this.ticket_.customMargins; |
| + }, |
| + |
| + // TODO Store the custom margins as a string so that validation can be done |
| + // in the PrintTicketStore. |
| + |
| + /** |
| + * Updates the custom margins of the document. Dispatches a TICKET_CHANGE |
| + * event if the margins have changed. |
| + * @param {print_preview.Margins} margins New document page margins. |
| + */ |
| + updateCustomMargins: function(margins) { |
| + if (!this.hasMarginsCapability()) { |
| + throw Error( |
| + 'Updating margins capability but destination does not have a ' + |
| + 'margin capability'); |
| + } |
| + if (!margins.equals(this.ticket_.customMargins)) { |
| + this.ticket_.customMargins = margins; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** @return {boolean} Whether the page range capability is available. */ |
| + hasPageRangeCapability: function() { |
| + // Page range can always be manipulated by Chromium. |
| + return true; |
| + }, |
| + |
| + /** |
| + * @return {boolean} Whether the current page range string is defines a |
| + * valid page number set. |
| + */ |
| + isPageRangeValid: function() { |
| + var pageRangeStr = this.ticket_.pageRangeStr; |
| + return pageRangeStr == '' || |
| + isPageRangeTextValid(pageRangeStr, this.documentInfo_.pageCount); |
| + }, |
| + |
| + /** @return {string} String representation of the page range. */ |
| + getPageRangeStr: function() { |
| + return this.ticket_.pageRangeStr; |
| + }, |
| + |
| + /** |
| + * @return {!print_preview.PageNumberSet} Page number set specified by the |
| + * string representation of the page range string. |
| + */ |
| + getPageNumberSet: function() { |
| + if (this.pageNumberSet_ == null) { |
| + this.pageNumberSet_ = print_preview.PageNumberSet.parse( |
| + this.ticket_.pageRangeStr, this.documentInfo_.pageCount); |
| + } |
| + return this.pageNumberSet_; |
| + }, |
| + |
| + /** |
| + * Updates the page range string. Dispatches a TICKET_CHANGE if the string |
| + * changed. |
| + * @param {string} pageRangeStr New page range string. |
| + */ |
| + updatePageRange: function(pageRangeStr) { |
| + if (this.ticket_.pageRangeStr != pageRangeStr) { |
| + this.ticket_.pageRangeStr = pageRangeStr; |
| + this.pageNumberSet_ = null; |
| + cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
| + } |
| + }, |
| + |
| + /** |
| + * @return {boolean} {@code true} if the stored print ticket is valid, |
| + * {@code false} otherwise. |
| + */ |
| + isTicketValid: function() { |
| + // TODO Validate custom margins |
| + return this.isCopiesValid() && this.isPageRangeValid(); |
| + } |
| + }; |
| + |
| + /** |
| + * Object which contains information related to the document to print. |
| + * |
| + * @constructor |
| + */ |
| + function DocumentInfo() { |
| + /** |
| + * Whether the document to print is modifiable (i.e. can be reflowed). |
| + * @type {boolean} |
| + */ |
| + this.isModifiable = true; |
| + |
| + /** |
| + * Number of pages in the document to print. |
| + * @type {number} |
| + */ |
| + this.pageCount = 1; |
| + |
| + /** |
| + * Size of the pages of the document. |
| + * @type {!print_preview.Size} |
| + */ |
| + this.pageSize = new print_preview.Size(612, 792); |
|
dpapad
2012/04/24 01:24:56
Where do these values come from?
Robert Toscano
2012/04/24 22:29:56
8.5"x11" paper size. I've move the initialization
|
| + |
| + /** |
| + * Printable area of the document. |
| + * @type {!print_preview.PrintableArea} |
| + */ |
| + this.printableArea = new print_preview.PrintableArea( |
| + new print_preview.Coordinate2d(0, 0), |
| + this.pageSize); |
| + }; |
| + |
| + // Export |
| + return { |
| + PrintTicketStore: PrintTicketStore |
| + }; |
| +}); |