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..4735eb740a35ed9d0f79458afc40831fcc817837 |
--- /dev/null |
+++ b/chrome/browser/resources/print_preview/data/print_ticket_store.js |
@@ -0,0 +1,532 @@ |
+// 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. |
+ * |
+ * @param {print_preview.DestinationStore!} destinationStore Destination store |
+ * used to get the selected destination. |
+ * @constructor |
+ * @extends {cr.EventTarget} |
+ */ |
+ function PrintTicketStore(destinationStore) { |
+ cr.EventTarget.call(this); |
+ |
+ /** |
+ * Destination store used to get the selected destination. |
+ * @type {print_preview.DestinationStore!} |
+ * @private |
+ */ |
+ this.destinationStore_ = destinationStore; |
+ |
+ /** |
+ * 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 = { |
dpapad1
2012/04/26 16:04:44
Nit: Should this be PrintTicketStore.EventType (li
Robert Toscano
2012/04/28 01:41:37
Done.
|
+ 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' |
+ }; |
+ |
+ PrintTicketStore.prototype = { |
+ __proto__: cr.EventTarget.prototype, |
+ |
+ get isInitialized() { |
+ return !!this.ticket_; |
+ }, |
+ |
+ get isDocumentModifiable() { |
+ return this.documentInfo_.isModifiable; |
+ }, |
+ |
+ get pageCount() { |
+ return this.documentInfo_.pageCount; |
+ }, |
+ |
+ updatePageCount: function(pageCount) { |
+ if (this.documentInfo_.pageCount != pageCount) { |
+ this.documentInfo_.pageCount = pageCount; |
+ this.pageNumberSet_ = null; |
+ cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); |
+ } |
+ }, |
+ |
+ get printableArea() { |
+ return this.documentInfo_.printableArea; |
+ }, |
+ |
+ 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); |
+ } |
+ }, |
+ |
+ get pageSize() { |
+ return this.documentInfo_.pageSize; |
+ }, |
+ |
+ 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); |
+ } |
+ }, |
+ |
+ get measurementSystem() { |
+ return this.measurementSystem_; |
+ }, |
+ |
+ /** @override */ |
+ dispatchEvent: function(evt) { |
+ // TODO REMOVE ME |
+ log(evt.type); |
+ cr.EventTarget.prototype.dispatchEvent.call(this, evt); |
+ }, |
+ |
+ /** |
+ * Initializes the print ticket store. |
+ * @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 {Object} customMarginsInfo Object describing the last used |
+ * margins. |
+ * @param {string} numberFormat A string describing the thousands and |
+ * decimal delimeters. |
+ * @param {print_preview.MeasurementSystem.UnitType} unitType Measurement |
+ * unit type of the local system. |
+ */ |
+ initialize: function( |
+ isDocumentModifiable, |
+ isDuplexEnabled, |
+ isHeaderFooterEnabled, |
+ marginsType, |
+ customMarginsInfo, |
+ numberFormat, |
+ unitType) { |
+ |
+ this.documentInfo_.isModifiable = isDocumentModifiable; |
+ |
+ // Create capabilities that can be handled by Chromium. |
+ this.capabilities_ = new print_preview.ChromiumCapabilities(); |
+ this.capabilities_.hasPageRangeCapability = true; |
+ this.capabilities_.hasColorCapability = true; |
+ this.capabilities_.hasCopiesCapability = true; |
+ this.capabilities_.hasCollateCapability = true; |
+ this.capabilities_.hasDuplexCapability = true; |
+ if (isDocumentModifiable) { |
+ this.capabilities_.hasOrientationCapability = true; |
+ this.capabilities_.hasMarginsCapability = true; |
+ this.capabilities_.hasHeaderFooterCapability = true; |
+ } |
+ |
+ // Initialize ticket with user's previous values. |
+ this.ticket_ = new print_preview.ChromiumPrintTicket(this.capabilities_); |
+ this.ticket_.isDuplexEnabled = isDuplexEnabled; |
+ this.ticket_.marginsType = marginsType != null ? |
+ marginsType : print_preview.Margins.Type.DEFAULT; |
+ if (customMarginsInfo != null) { |
+ this.ticket_.customMargins = new print_preview.Margins( |
+ customMarginsInfo[0], customMarginsInfo[1], |
+ customMarginsInfo[2], customMarginsInfo[3]); |
+ } |
+ this.ticket_.isHeaderFooterEnabled = isHeaderFooterEnabled; |
+ |
+ // Initialize measurement system. |
+ var numberFormatSymbols = |
+ print_preview.MeasurementSystem.parseNumberFormat(numberFormat); |
+ this.measurementSystem_ = new print_preview.MeasurementSystem( |
+ numberFormatSymbols[0], numberFormatSymbols[1], unitType); |
+ |
+ cr.dispatchSimpleEvent(this, PrintTicketStore.Event.INITIALIZE); |
+ }, |
+ |
+ updateDestinationCapabilities: function(caps) { |
+ if (this.capabilities_.hasPageRangeCapability = |
+ caps.hasPageRangeCapability) { |
+ this.capabilities_.defaultPageRangeStr = caps.defaultPageRangeStr; |
+ } |
+ if (this.capabilities_.hasColorCapability = caps.hasColorCapability) { |
+ this.capabilities_.defaultIsColorEnabled = caps.defaultIsColorEnabled; |
+ } |
+ if (this.capabilities_.hasCopiesCapability = caps.hasCopiesCapability) { |
+ this.capabilities_.defaultCopiesStr = caps.defaultCopiesStr; |
+ } |
+ if (this.capabilities_.hasCollateCapability = caps.hasCollateCapability) { |
+ this.capabilities_.defaultIsCollateEnabled = |
+ caps.defaultIsCollateEnabled; |
+ } |
+ if (this.capabilities_.hasDuplexCapability = caps.hasDuplexCapability) { |
+ this.capabilities_.defaultIsDuplexEnabled = caps.defaultIsDuplexEnabled; |
+ } |
+ if (this.documentInfo_.isModifiable) { |
+ if (this.capabilities_.hasOrientationCapability = |
+ caps.hasOrientationCapability) { |
+ this.capabilities_.defaultIsLandscapeEnabled = |
+ caps.defaultIsLandscapeEnabled; |
+ } |
+ if (this.capabilities_.hasMarginsCapability = |
+ caps.hasMarginsCapability) { |
+ this.capabilities_.defaultMarginsType = caps.defaultMarginsType; |
+ } |
+ if (this.capabilities_.hasHeaderFooterCapability = |
+ caps.hasHeaderFooterCapability) { |
+ this.capabilities_.defaultIsHeaderFooterEnabled = |
+ caps.defaultIsHeaderFooterEnabled; |
+ } |
+ } |
+ cr.dispatchSimpleEvent(this, PrintTicketStore.Event.CAPABILITIES_CHANGE); |
+ }, |
+ |
+ hasCopiesCapability: function() { |
+ return this.capabilities_.hasCopiesCapability; |
+ }, |
+ |
+ isCopiesValid: function() { |
+ return this.isCopiesValidForValue(this.ticket_.copiesStr); |
+ }, |
+ |
+ isCopiesValidForValue: function(value) { |
dpapad1
2012/04/26 16:04:44
This method should be static (or a util method in
Robert Toscano
2012/04/28 01:41:37
Done.
|
+ if (/[^\d]+/.test(value)) { |
+ return false; |
+ } |
+ var copies = parseInt(value); |
+ if (copies > 999 || copies < 1) { |
+ return false; |
+ } |
+ return true; |
+ }, |
+ |
+ getCopies: function() { |
+ return parseInt(this.ticket_.copiesStr); |
+ }, |
+ |
+ getCopiesStr: function() { |
+ return this.ticket_.copiesStr; |
+ }, |
+ |
+ updateCopies: function(copies) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ hasCollateCapability: function() { |
+ return this.capabilities_.hasCollateCapability; |
+ }, |
+ |
+ isCollateEnabled: function() { |
+ return this.ticket_.isCollateEnabled; |
+ }, |
+ |
+ updateCollate: function(isCollate) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ hasColorCapability: function() { |
+ return this.capabilities_.hasColorCapability; |
+ }, |
+ |
+ isColorEnabled: function() { |
+ return this.ticket_.isColorEnabled; |
+ }, |
+ |
+ getColorMode: function() { |
+ return this.ticket_.colorMode; |
+ }, |
+ |
+ /** |
+ * @param {boolean} isColor Whether the color option is enabled. |
+ */ |
+ updateColor: function(isColor) { |
+ if (!this.capabilities_.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() { |
+ if (!this.capabilities_.hasHeaderFooterCapability) { |
+ return false; |
+ } |
+ // Checks the printable area and updates the visibility of header footer |
+ // option based on the selected margins. |
+ if (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; |
+ var printableArea = this.documentInfo_.printableArea; |
+ var pageSize = this.documentInfo_.pageSize; |
+ if (margins.top < printableArea.origin.y || |
+ margins.bottom < pageSize.height - printableArea.origin.y - |
+ printableArea.size.height) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ }, |
+ |
+ /** @return {boolean} Whether the header-footer setting is enabled. */ |
+ isHeaderFooterEnabled: function() { |
+ return this.ticket_.isHeaderFooterEnabled; |
+ }, |
+ |
+ updateHeaderFooter: function(isHeaderFooterEnabled) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ hasOrientationCapability: function() { |
+ // TODO Is this true? Maybe we can still rotate if the document is not |
+ // modifiable. This is the old behavior. |
+ return this.capabilities_.hasOrientationCapability; |
+ }, |
+ |
+ isLandscapeEnabled: function() { |
+ return this.ticket_.isLandscapeEnabled; |
+ }, |
+ |
+ updateOrientation: function(isLandscape) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ hasDuplexCapability: function() { |
+ return this.capabilities_.hasDuplexCapability; |
+ }, |
+ |
+ isDuplexEnabled: function() { |
+ return this.ticket_.isDuplexEnabled; |
+ }, |
+ |
+ getDuplexMode: function() { |
+ return this.ticket_.duplexMode; |
+ }, |
+ |
+ updateDuplex: function(isDuplex) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ hasMarginsCapability: function() { |
+ return this.capabilities_.hasMarginsCapability; |
+ }, |
+ |
+ getMarginsType: function() { |
+ return this.ticket_.marginsType; |
+ }, |
+ |
+ updateMarginsType: function(marginsType) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ getCustomMargins: function() { |
+ return this.ticket_.customMargins; |
+ }, |
+ |
+ updateCustomMargins: function(margins) { |
+ if (!this.capabilities_.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); |
+ } |
+ }, |
+ |
+ hasPageRangeCapability: function() { |
+ return this.capabilities_.hasPageRangeCapability; |
+ }, |
+ |
+ isPageRangeValid: function() { |
+ var pageRangeStr = this.ticket_.pageRangeStr; |
+ return pageRangeStr == '' || |
+ isPageRangeTextValid(pageRangeStr, this.documentInfo_.pageCount); |
+ }, |
+ |
+ getPageRangeStr: function() { |
+ return this.ticket_.pageRangeStr; |
+ }, |
+ |
+ getPageNumberSet: function() { |
+ if (this.pageNumberSet_ == null) { |
+ this.pageNumberSet_ = print_preview.PageNumberSet.parse( |
+ this.ticket_.pageRangeStr, this.documentInfo_.pageCount); |
+ } |
+ return this.pageNumberSet_; |
+ }, |
+ |
+ updatePageRange: function(pageRangeStr) { |
+ if (!this.capabilities_.hasPageRangeCapability) { |
+ throw Error( |
+ 'Updating page-range capability but destination does not have a ' + |
+ 'page-range capability'); |
+ } |
+ if (this.ticket_.pageRangeStr != pageRangeStr) { |
+ this.ticket_.pageRangeStr = pageRangeStr; |
+ this.pageNumberSet_ = null; |
+ cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); |
+ } |
+ }, |
+ |
+ /** |
+ * Checking if the stored print ticket is valid. |
+ * @return {boolean} {@code true} if the stored print ticket is valid, |
+ * {@code false} otherwise. |
+ */ |
+ isTicketValid: function() { |
+ // TODO Validate 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); |
+ |
+ /** |
+ * Printable area of the document. |
+ * @type {print_preview.PrintableArea!} |
+ */ |
+ this.printableArea = new print_preview.PrintableArea( |
+ new print_preview.Coordinate2d(0, 0), |
+ this.pageSize); |
+ |
+ /** |
+ * TODO |
+ * @type {boolean} |
+ */ |
+ this.hasPageSizeStyle = false; |
+ }; |
+ |
+ // Export |
+ return { |
+ PrintTicketStore: PrintTicketStore |
+ }; |
+}); |