OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 // TODO Optimize this to not dispatch CHANGE events when nothing really changed. | |
6 | |
7 cr.define('print_preview', function() { | |
8 'use strict'; | |
9 | |
10 /** | |
11 * Storage of the print ticket and document statistics. | |
12 * | |
13 * Dispatches events when the contents of the print ticket or document | |
14 * statistics change. Also handles validation of the print ticket against | |
15 * destination capabilities and against the document. | |
16 * | |
17 * @param {print_preview.DestinationStore!} destinationStore Destination store | |
18 * used to get the selected destination. | |
19 * @constructor | |
20 * @extends {cr.EventTarget} | |
21 */ | |
22 function PrintTicketStore(destinationStore) { | |
23 cr.EventTarget.call(this); | |
24 | |
25 /** | |
26 * Destination store used to get the selected destination. | |
27 * @type {print_preview.DestinationStore!} | |
28 * @private | |
29 */ | |
30 this.destinationStore_ = destinationStore; | |
31 | |
32 /** | |
33 * Information about the document to print. | |
34 * @type {DocumentInfo} | |
35 * @private | |
36 */ | |
37 this.documentInfo_ = new DocumentInfo(); | |
38 | |
39 /** | |
40 * Printing capabilities of Chromium and the currently selected destination. | |
41 * @type {print_preview.ChromiumCapabilities} | |
42 * @private | |
43 */ | |
44 this.capabilities_ = null; | |
45 | |
46 /** | |
47 * Print ticket information. Used to print and generate previews. | |
48 * @type {print_preview.ChromiumPrintTicket} | |
49 * @private | |
50 */ | |
51 this.ticket_ = null; | |
52 | |
53 /** | |
54 * Current measurement system. Used to work with margin measurements. | |
55 * @type {print_preview.MeasurementSystem} | |
56 * @private | |
57 */ | |
58 this.measurementSystem_ = null; | |
59 | |
60 /** | |
61 * Cached page number set. Used to not have to parse page range string | |
62 * everytime its requested. | |
63 * @type {print_preview.PageNumberSet} | |
64 * @private | |
65 */ | |
66 this.pageNumberSet_ = null; | |
67 }; | |
68 | |
69 /** | |
70 * Events dispatched by the print ticket store. | |
71 * @enum {string} | |
72 */ | |
73 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.
| |
74 CAPABILITIES_CHANGE: 'print_preview.PrintTicketStore.CAPABILITIES_CHANGE', | |
75 DOCUMENT_CHANGE: 'print_preview.PrintTicketStore.DOCUMENT_CHANGE', | |
76 INITIALIZE: 'print_preview.PrintTicketStore.INITIALIZE', | |
77 TICKET_CHANGE: 'print_preview.PrintTicketStore.TICKET_CHANGE' | |
78 }; | |
79 | |
80 PrintTicketStore.prototype = { | |
81 __proto__: cr.EventTarget.prototype, | |
82 | |
83 get isInitialized() { | |
84 return !!this.ticket_; | |
85 }, | |
86 | |
87 get isDocumentModifiable() { | |
88 return this.documentInfo_.isModifiable; | |
89 }, | |
90 | |
91 get pageCount() { | |
92 return this.documentInfo_.pageCount; | |
93 }, | |
94 | |
95 updatePageCount: function(pageCount) { | |
96 if (this.documentInfo_.pageCount != pageCount) { | |
97 this.documentInfo_.pageCount = pageCount; | |
98 this.pageNumberSet_ = null; | |
99 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); | |
100 } | |
101 }, | |
102 | |
103 get printableArea() { | |
104 return this.documentInfo_.printableArea; | |
105 }, | |
106 | |
107 updatePrintableArea: function(printableArea) { | |
108 if (!this.documentInfo_.printableArea.equals(printableArea)) { | |
109 log('PrintableArea: ' + printableArea.origin.x + ' ' + | |
110 printableArea.origin.y + ' ' + printableArea.size.width + ' ' + | |
111 printableArea.size.height); | |
112 this.documentInfo_.printableArea = printableArea; | |
113 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); | |
114 } | |
115 }, | |
116 | |
117 get pageSize() { | |
118 return this.documentInfo_.pageSize; | |
119 }, | |
120 | |
121 updatePageSize: function(pageSize) { | |
122 if (!this.documentInfo_.pageSize.equals(pageSize)) { | |
123 log('Updating page size to: ' + pageSize.width + ' ' + pageSize.height); | |
124 this.documentInfo_.pageSize = pageSize; | |
125 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.DOCUMENT_CHANGE); | |
126 } | |
127 }, | |
128 | |
129 get measurementSystem() { | |
130 return this.measurementSystem_; | |
131 }, | |
132 | |
133 /** @override */ | |
134 dispatchEvent: function(evt) { | |
135 // TODO REMOVE ME | |
136 log(evt.type); | |
137 cr.EventTarget.prototype.dispatchEvent.call(this, evt); | |
138 }, | |
139 | |
140 /** | |
141 * Initializes the print ticket store. | |
142 * @param {boolean} isDocumentModifiable Whether the document to print is | |
143 * modifiable (i.e. can be re-flowed by Chromium). | |
144 * @param {boolean} isDuplexEnabled Previous duplex setting. | |
145 * @param {boolean} isHeaderFooterEnabled Previous header-footer setting. | |
146 * @param {print_preview.Margins.Type} marginsType Previous margins type. | |
147 * @param {Object} customMarginsInfo Object describing the last used | |
148 * margins. | |
149 * @param {string} numberFormat A string describing the thousands and | |
150 * decimal delimeters. | |
151 * @param {print_preview.MeasurementSystem.UnitType} unitType Measurement | |
152 * unit type of the local system. | |
153 */ | |
154 initialize: function( | |
155 isDocumentModifiable, | |
156 isDuplexEnabled, | |
157 isHeaderFooterEnabled, | |
158 marginsType, | |
159 customMarginsInfo, | |
160 numberFormat, | |
161 unitType) { | |
162 | |
163 this.documentInfo_.isModifiable = isDocumentModifiable; | |
164 | |
165 // Create capabilities that can be handled by Chromium. | |
166 this.capabilities_ = new print_preview.ChromiumCapabilities(); | |
167 this.capabilities_.hasPageRangeCapability = true; | |
168 this.capabilities_.hasColorCapability = true; | |
169 this.capabilities_.hasCopiesCapability = true; | |
170 this.capabilities_.hasCollateCapability = true; | |
171 this.capabilities_.hasDuplexCapability = true; | |
172 if (isDocumentModifiable) { | |
173 this.capabilities_.hasOrientationCapability = true; | |
174 this.capabilities_.hasMarginsCapability = true; | |
175 this.capabilities_.hasHeaderFooterCapability = true; | |
176 } | |
177 | |
178 // Initialize ticket with user's previous values. | |
179 this.ticket_ = new print_preview.ChromiumPrintTicket(this.capabilities_); | |
180 this.ticket_.isDuplexEnabled = isDuplexEnabled; | |
181 this.ticket_.marginsType = marginsType != null ? | |
182 marginsType : print_preview.Margins.Type.DEFAULT; | |
183 if (customMarginsInfo != null) { | |
184 this.ticket_.customMargins = new print_preview.Margins( | |
185 customMarginsInfo[0], customMarginsInfo[1], | |
186 customMarginsInfo[2], customMarginsInfo[3]); | |
187 } | |
188 this.ticket_.isHeaderFooterEnabled = isHeaderFooterEnabled; | |
189 | |
190 // Initialize measurement system. | |
191 var numberFormatSymbols = | |
192 print_preview.MeasurementSystem.parseNumberFormat(numberFormat); | |
193 this.measurementSystem_ = new print_preview.MeasurementSystem( | |
194 numberFormatSymbols[0], numberFormatSymbols[1], unitType); | |
195 | |
196 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.INITIALIZE); | |
197 }, | |
198 | |
199 updateDestinationCapabilities: function(caps) { | |
200 if (this.capabilities_.hasPageRangeCapability = | |
201 caps.hasPageRangeCapability) { | |
202 this.capabilities_.defaultPageRangeStr = caps.defaultPageRangeStr; | |
203 } | |
204 if (this.capabilities_.hasColorCapability = caps.hasColorCapability) { | |
205 this.capabilities_.defaultIsColorEnabled = caps.defaultIsColorEnabled; | |
206 } | |
207 if (this.capabilities_.hasCopiesCapability = caps.hasCopiesCapability) { | |
208 this.capabilities_.defaultCopiesStr = caps.defaultCopiesStr; | |
209 } | |
210 if (this.capabilities_.hasCollateCapability = caps.hasCollateCapability) { | |
211 this.capabilities_.defaultIsCollateEnabled = | |
212 caps.defaultIsCollateEnabled; | |
213 } | |
214 if (this.capabilities_.hasDuplexCapability = caps.hasDuplexCapability) { | |
215 this.capabilities_.defaultIsDuplexEnabled = caps.defaultIsDuplexEnabled; | |
216 } | |
217 if (this.documentInfo_.isModifiable) { | |
218 if (this.capabilities_.hasOrientationCapability = | |
219 caps.hasOrientationCapability) { | |
220 this.capabilities_.defaultIsLandscapeEnabled = | |
221 caps.defaultIsLandscapeEnabled; | |
222 } | |
223 if (this.capabilities_.hasMarginsCapability = | |
224 caps.hasMarginsCapability) { | |
225 this.capabilities_.defaultMarginsType = caps.defaultMarginsType; | |
226 } | |
227 if (this.capabilities_.hasHeaderFooterCapability = | |
228 caps.hasHeaderFooterCapability) { | |
229 this.capabilities_.defaultIsHeaderFooterEnabled = | |
230 caps.defaultIsHeaderFooterEnabled; | |
231 } | |
232 } | |
233 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.CAPABILITIES_CHANGE); | |
234 }, | |
235 | |
236 hasCopiesCapability: function() { | |
237 return this.capabilities_.hasCopiesCapability; | |
238 }, | |
239 | |
240 isCopiesValid: function() { | |
241 return this.isCopiesValidForValue(this.ticket_.copiesStr); | |
242 }, | |
243 | |
244 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.
| |
245 if (/[^\d]+/.test(value)) { | |
246 return false; | |
247 } | |
248 var copies = parseInt(value); | |
249 if (copies > 999 || copies < 1) { | |
250 return false; | |
251 } | |
252 return true; | |
253 }, | |
254 | |
255 getCopies: function() { | |
256 return parseInt(this.ticket_.copiesStr); | |
257 }, | |
258 | |
259 getCopiesStr: function() { | |
260 return this.ticket_.copiesStr; | |
261 }, | |
262 | |
263 updateCopies: function(copies) { | |
264 if (!this.capabilities_.hasCopiesCapability) { | |
265 throw Error( | |
266 'Updating copies capability but destination does not have a ' + | |
267 'copies capability'); | |
268 } | |
269 if (this.ticket_.copiesStr != copies) { | |
270 this.ticket_.copiesStr = copies; | |
271 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
272 } | |
273 }, | |
274 | |
275 hasCollateCapability: function() { | |
276 return this.capabilities_.hasCollateCapability; | |
277 }, | |
278 | |
279 isCollateEnabled: function() { | |
280 return this.ticket_.isCollateEnabled; | |
281 }, | |
282 | |
283 updateCollate: function(isCollate) { | |
284 if (!this.capabilities_.hasCollateCapability) { | |
285 throw Error( | |
286 'Updating collate capability but destination does not have a ' + | |
287 'collate capability'); | |
288 } | |
289 if (this.ticket_.isCollateEnabled != isCollate) { | |
290 this.ticket_.isCollateEnabled = isCollate; | |
291 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
292 } | |
293 }, | |
294 | |
295 hasColorCapability: function() { | |
296 return this.capabilities_.hasColorCapability; | |
297 }, | |
298 | |
299 isColorEnabled: function() { | |
300 return this.ticket_.isColorEnabled; | |
301 }, | |
302 | |
303 getColorMode: function() { | |
304 return this.ticket_.colorMode; | |
305 }, | |
306 | |
307 /** | |
308 * @param {boolean} isColor Whether the color option is enabled. | |
309 */ | |
310 updateColor: function(isColor) { | |
311 if (!this.capabilities_.hasColorCapability) { | |
312 throw Error( | |
313 'Updating color capability but destination does not have a color ' + | |
314 'capability'); | |
315 } | |
316 if (this.ticket_.isColorEnabled != isColor) { | |
317 this.ticket_.isColorEnabled = isColor; | |
318 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
319 } | |
320 }, | |
321 | |
322 /** @return {boolean} Whether the header-footer capability is available. */ | |
323 hasHeaderFooterCapability: function() { | |
324 if (!this.capabilities_.hasHeaderFooterCapability) { | |
325 return false; | |
326 } | |
327 // Checks the printable area and updates the visibility of header footer | |
328 // option based on the selected margins. | |
329 if (this.ticket_.marginsType == print_preview.Margins.Type.NO_MARGINS) { | |
330 return false; | |
331 } | |
332 if (this.ticket_.marginsType == print_preview.Margins.Type.CUSTOM) { | |
333 var margins = this.ticket_.customMargins; | |
334 var printableArea = this.documentInfo_.printableArea; | |
335 var pageSize = this.documentInfo_.pageSize; | |
336 if (margins.top < printableArea.origin.y || | |
337 margins.bottom < pageSize.height - printableArea.origin.y - | |
338 printableArea.size.height) { | |
339 return false; | |
340 } | |
341 } | |
342 return true; | |
343 }, | |
344 | |
345 /** @return {boolean} Whether the header-footer setting is enabled. */ | |
346 isHeaderFooterEnabled: function() { | |
347 return this.ticket_.isHeaderFooterEnabled; | |
348 }, | |
349 | |
350 updateHeaderFooter: function(isHeaderFooterEnabled) { | |
351 if (!this.capabilities_.hasHeaderFooterCapability) { | |
352 throw Error( | |
353 'Updating header-footer capability but destination does not have ' + | |
354 'a header-footer capability'); | |
355 } | |
356 if (this.ticket_.isHeaderFooterEnabled != isHeaderFooterEnabled) { | |
357 this.ticket_.isHeaderFooterEnabled = isHeaderFooterEnabled; | |
358 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
359 } | |
360 }, | |
361 | |
362 hasOrientationCapability: function() { | |
363 // TODO Is this true? Maybe we can still rotate if the document is not | |
364 // modifiable. This is the old behavior. | |
365 return this.capabilities_.hasOrientationCapability; | |
366 }, | |
367 | |
368 isLandscapeEnabled: function() { | |
369 return this.ticket_.isLandscapeEnabled; | |
370 }, | |
371 | |
372 updateOrientation: function(isLandscape) { | |
373 if (!this.capabilities_.hasOrientationCapability) { | |
374 throw Error( | |
375 'Updating orientation capability but destination does not have ' + | |
376 'an orientation capability'); | |
377 } | |
378 if (this.ticket_.isLandscapeEnabled != isLandscape) { | |
379 this.ticket_.isLandscapeEnabled = isLandscape; | |
380 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
381 } | |
382 }, | |
383 | |
384 hasDuplexCapability: function() { | |
385 return this.capabilities_.hasDuplexCapability; | |
386 }, | |
387 | |
388 isDuplexEnabled: function() { | |
389 return this.ticket_.isDuplexEnabled; | |
390 }, | |
391 | |
392 getDuplexMode: function() { | |
393 return this.ticket_.duplexMode; | |
394 }, | |
395 | |
396 updateDuplex: function(isDuplex) { | |
397 if (!this.capabilities_.hasDuplexCapability) { | |
398 throw Error( | |
399 'Updating duplex capability but destination does not have a ' + | |
400 'duplex capability'); | |
401 } | |
402 if (this.ticket_.isDuplexEnabled != isDuplex) { | |
403 this.ticket_.isDuplexEnabled = isDuplex; | |
404 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
405 } | |
406 }, | |
407 | |
408 hasMarginsCapability: function() { | |
409 return this.capabilities_.hasMarginsCapability; | |
410 }, | |
411 | |
412 getMarginsType: function() { | |
413 return this.ticket_.marginsType; | |
414 }, | |
415 | |
416 updateMarginsType: function(marginsType) { | |
417 if (!this.capabilities_.hasMarginsCapability) { | |
418 throw Error( | |
419 'Updating margins capability but destination does not have a ' + | |
420 'margin capability'); | |
421 } | |
422 if (this.ticket_.marginsType != marginsType) { | |
423 this.ticket_.marginsType = marginsType; | |
424 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
425 } | |
426 }, | |
427 | |
428 getCustomMargins: function() { | |
429 return this.ticket_.customMargins; | |
430 }, | |
431 | |
432 updateCustomMargins: function(margins) { | |
433 if (!this.capabilities_.hasMarginsCapability) { | |
434 throw Error( | |
435 'Updating margins capability but destination does not have a ' + | |
436 'margin capability'); | |
437 } | |
438 if (!margins.equals(this.ticket_.customMargins)) { | |
439 this.ticket_.customMargins = margins; | |
440 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
441 } | |
442 }, | |
443 | |
444 hasPageRangeCapability: function() { | |
445 return this.capabilities_.hasPageRangeCapability; | |
446 }, | |
447 | |
448 isPageRangeValid: function() { | |
449 var pageRangeStr = this.ticket_.pageRangeStr; | |
450 return pageRangeStr == '' || | |
451 isPageRangeTextValid(pageRangeStr, this.documentInfo_.pageCount); | |
452 }, | |
453 | |
454 getPageRangeStr: function() { | |
455 return this.ticket_.pageRangeStr; | |
456 }, | |
457 | |
458 getPageNumberSet: function() { | |
459 if (this.pageNumberSet_ == null) { | |
460 this.pageNumberSet_ = print_preview.PageNumberSet.parse( | |
461 this.ticket_.pageRangeStr, this.documentInfo_.pageCount); | |
462 } | |
463 return this.pageNumberSet_; | |
464 }, | |
465 | |
466 updatePageRange: function(pageRangeStr) { | |
467 if (!this.capabilities_.hasPageRangeCapability) { | |
468 throw Error( | |
469 'Updating page-range capability but destination does not have a ' + | |
470 'page-range capability'); | |
471 } | |
472 if (this.ticket_.pageRangeStr != pageRangeStr) { | |
473 this.ticket_.pageRangeStr = pageRangeStr; | |
474 this.pageNumberSet_ = null; | |
475 cr.dispatchSimpleEvent(this, PrintTicketStore.Event.TICKET_CHANGE); | |
476 } | |
477 }, | |
478 | |
479 /** | |
480 * Checking if the stored print ticket is valid. | |
481 * @return {boolean} {@code true} if the stored print ticket is valid, | |
482 * {@code false} otherwise. | |
483 */ | |
484 isTicketValid: function() { | |
485 // TODO Validate margins | |
486 return this.isCopiesValid() && this.isPageRangeValid(); | |
487 } | |
488 }; | |
489 | |
490 /** | |
491 * Object which contains information related to the document to print. | |
492 * @constructor | |
493 */ | |
494 function DocumentInfo() { | |
495 /** | |
496 * Whether the document to print is modifiable (i.e. can be reflowed). | |
497 * @type {boolean} | |
498 */ | |
499 this.isModifiable = true; | |
500 | |
501 /** | |
502 * Number of pages in the document to print. | |
503 * @type {number} | |
504 */ | |
505 this.pageCount = 1; | |
506 | |
507 /** | |
508 * Size of the pages of the document. | |
509 * @type {print_preview.Size!} | |
510 */ | |
511 this.pageSize = new print_preview.Size(612, 792); | |
512 | |
513 /** | |
514 * Printable area of the document. | |
515 * @type {print_preview.PrintableArea!} | |
516 */ | |
517 this.printableArea = new print_preview.PrintableArea( | |
518 new print_preview.Coordinate2d(0, 0), | |
519 this.pageSize); | |
520 | |
521 /** | |
522 * TODO | |
523 * @type {boolean} | |
524 */ | |
525 this.hasPageSizeStyle = false; | |
526 }; | |
527 | |
528 // Export | |
529 return { | |
530 PrintTicketStore: PrintTicketStore | |
531 }; | |
532 }); | |
OLD | NEW |