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 5cr.define('print_preview', function() { 6 'use strict'; 7 8 // TODO(rltoscano): Maybe clear print ticket when destination changes. Or 9 // better yet, carry over any print ticket state that is possible. I.e. if 10 // destination changes, the new destination might not support duplex anymore, 11 // so we should clear the ticket's isDuplexEnabled state. 12 13 /** 14 * Storage of the print ticket and document statistics. Dispatches events when 15 * the contents of the print ticket or document statistics change. Also 16 * handles validation of the print ticket against destination capabilities and 17 * against the document. 18 * @param {!print_preview.DestinationStore} destinationStore Used to 19 * understand which printer is selected. 20 * @param {!print_preview.AppState} appState Print preview application state. 21 * @param {!print_preview.DocumentInfo} documentInfo Document data model. 22 * @constructor 23 * @extends {cr.EventTarget} 24 */ 25 function PrintTicketStore(destinationStore, appState, documentInfo) { 26 cr.EventTarget.call(this); 27 28 /** 29 * Destination store used to understand which printer is selected. 30 * @type {!print_preview.DestinationStore} 31 * @private 32 */ 33 this.destinationStore_ = destinationStore; 34 35 /** 36 * App state used to persist and load ticket values. 37 * @type {!print_preview.AppState} 38 * @private 39 */ 40 this.appState_ = appState; 41 42 /** 43 * Information about the document to print. 44 * @type {!print_preview.DocumentInfo} 45 * @private 46 */ 47 this.documentInfo_ = documentInfo; 48 49 /** 50 * Printing capabilities of Chromium and the currently selected destination. 51 * @type {!print_preview.CapabilitiesHolder} 52 * @private 53 */ 54 this.capabilitiesHolder_ = new print_preview.CapabilitiesHolder(); 55 56 /** 57 * Current measurement system. Used to work with margin measurements. 58 * @type {!print_preview.MeasurementSystem} 59 * @private 60 */ 61 this.measurementSystem_ = new print_preview.MeasurementSystem( 62 ',', '.', print_preview.MeasurementSystem.UnitType.IMPERIAL); 63 64 /** 65 * Collate ticket item. 66 * @type {!print_preview.ticket_items.Collate} 67 * @private 68 */ 69 this.collate_ = new print_preview.ticket_items.Collate( 70 this.appState_, this.destinationStore_); 71 72 /** 73 * Color ticket item. 74 * @type {!print_preview.ticket_items.Color} 75 * @private 76 */ 77 this.color_ = new print_preview.ticket_items.Color( 78 this.appState_, this.destinationStore_); 79 80 /** 81 * Copies ticket item. 82 * @type {!print_preview.ticket_items.Copies} 83 * @private 84 */ 85 this.copies_ = 86 new print_preview.ticket_items.Copies(this.destinationStore_); 87 88 /** 89 * Duplex ticket item. 90 * @type {!print_preview.ticket_items.Duplex} 91 * @private 92 */ 93 this.duplex_ = new print_preview.ticket_items.Duplex( 94 this.appState_, this.destinationStore_); 95 96 /** 97 * Page range ticket item. 98 * @type {!print_preview.ticket_items.PageRange} 99 * @private 100 */ 101 this.pageRange_ = 102 new print_preview.ticket_items.PageRange(this.documentInfo_); 103 104 /** 105 * Custom margins ticket item. 106 * @type {!print_preview.ticket_items.CustomMargins} 107 * @private 108 */ 109 this.customMargins_ = new print_preview.ticket_items.CustomMargins( 110 this.appState_, this.documentInfo_); 111 112 /** 113 * Margins type ticket item. 114 * @type {!print_preview.ticket_items.MarginsType} 115 * @private 116 */ 117 this.marginsType_ = new print_preview.ticket_items.MarginsType( 118 this.appState_, this.documentInfo_, this.customMargins_); 119 120 /** 121 * Landscape ticket item. 122 * @type {!print_preview.ticket_items.Landscape} 123 * @private 124 */ 125 this.landscape_ = new print_preview.ticket_items.Landscape( 126 this.appState_, this.destinationStore_, this.documentInfo_, 127 this.marginsType_, this.customMargins_); 128 129 /** 130 * Header-footer ticket item. 131 * @type {!print_preview.ticket_items.HeaderFooter} 132 * @private 133 */ 134 this.headerFooter_ = new print_preview.ticket_items.HeaderFooter( 135 this.appState_, this.documentInfo_, this.marginsType_, 136 this.customMargins_); 137 138 /** 139 * Fit-to-page ticket item. 140 * @type {!print_preview.ticket_items.FitToPage} 141 * @private 142 */ 143 this.fitToPage_ = new print_preview.ticket_items.FitToPage( 144 this.documentInfo_, this.destinationStore_); 145 146 /** 147 * Print CSS backgrounds ticket item. 148 * @type {!print_preview.ticket_items.CssBackground} 149 * @private 150 */ 151 this.cssBackground_ = new print_preview.ticket_items.CssBackground( 152 this.appState_, this.documentInfo_); 153 154 /** 155 * Print selection only ticket item. 156 * @type {!print_preview.ticket_items.SelectionOnly} 157 * @private 158 */ 159 this.selectionOnly_ = 160 new print_preview.ticket_items.SelectionOnly(this.documentInfo_); 161 162 /** 163 * Keeps track of event listeners for the print ticket store. 164 * @type {!EventTracker} 165 * @private 166 */ 167 this.tracker_ = new EventTracker(); 168 169 /** 170 * Whether the print preview has been initialized. 171 * @type {boolean} 172 * @private 173 */ 174 this.isInitialized_ = false; 175 176 this.addEventListeners_(); 177 }; 178 179 /** 180 * Event types dispatched by the print ticket store. 181 * @enum {string} 182 */ 183 PrintTicketStore.EventType = { 184 CAPABILITIES_CHANGE: 'print_preview.PrintTicketStore.CAPABILITIES_CHANGE', 185 DOCUMENT_CHANGE: 'print_preview.PrintTicketStore.DOCUMENT_CHANGE', 186 INITIALIZE: 'print_preview.PrintTicketStore.INITIALIZE', 187 TICKET_CHANGE: 'print_preview.PrintTicketStore.TICKET_CHANGE' 188 }; 189 190 PrintTicketStore.prototype = { 191 __proto__: cr.EventTarget.prototype, 192 193 /** 194 * Whether the print preview has been initialized. 195 * @type {boolean} 196 */ 197 get isInitialized() { 198 return this.isInitialized_; 199 }, 200 201 get collate() { 202 return this.collate_; 203 }, 204 205 get color() { 206 return this.color_; 207 }, 208 209 get copies() { 210 return this.copies_; 211 }, 212 213 get cssBackground() { 214 return this.cssBackground_; 215 }, 216 217 get customMargins() { 218 return this.customMargins_; 219 }, 220 221 get duplex() { 222 return this.duplex_; 223 }, 224 225 get fitToPage() { 226 return this.fitToPage_; 227 }, 228 229 get headerFooter() { 230 return this.headerFooter_; 231 }, 232 233 get landscape() { 234 return this.landscape_; 235 }, 236 237 get marginsType() { 238 return this.marginsType_; 239 }, 240 241 get pageRange() { 242 return this.pageRange_; 243 }, 244 245 get selectionOnly() { 246 return this.selectionOnly_; 247 }, 248 249 /** 250 * @return {!print_preview.MeasurementSystem} Measurement system of the 251 * local system. 252 */ 253 get measurementSystem() { 254 return this.measurementSystem_; 255 }, 256 257 /** 258 * Initializes the print ticket store. Dispatches an INITIALIZE event. 259 * @param {string} thousandsDelimeter Delimeter of the thousands place. 260 * @param {string} decimalDelimeter Delimeter of the decimal point. 261 * @param {!print_preview.MeasurementSystem.UnitType} unitType Type of unit 262 * of the local measurement system. 263 * @param {boolean} selectionOnly Whether only selected content should be 264 * printed. 265 */ 266 init: function( 267 thousandsDelimeter, decimalDelimeter, unitType, selectionOnly) { 268 this.measurementSystem_.setSystem(thousandsDelimeter, decimalDelimeter, 269 unitType); 270 this.selectionOnly_.updateValue(selectionOnly); 271 272 // Initialize ticket with user's previous values. 273 if (this.appState_.hasField(print_preview.AppState.Field.MARGINS_TYPE)) { 274 this.marginsType_.updateValue( 275 this.appState_.getField(print_preview.AppState.Field.MARGINS_TYPE)); 276 } 277 if (this.appState_.hasField( 278 print_preview.AppState.Field.CUSTOM_MARGINS)) { 279 this.customMargins_.updateValue(this.appState_.getField( 280 print_preview.AppState.Field.CUSTOM_MARGINS)); 281 } 282 if (this.appState_.hasField( 283 print_preview.AppState.Field.IS_COLOR_ENABLED)) { 284 this.color_.updateValue(this.appState_.getField( 285 print_preview.AppState.Field.IS_COLOR_ENABLED)); 286 } 287 if (this.appState_.hasField( 288 print_preview.AppState.Field.IS_DUPLEX_ENABLED)) { 289 this.duplex_.updateValue(this.appState_.getField( 290 print_preview.AppState.Field.IS_DUPLEX_ENABLED)); 291 } 292 if (this.appState_.hasField( 293 print_preview.AppState.Field.IS_HEADER_FOOTER_ENABLED)) { 294 this.headerFooter_.updateValue(this.appState_.getField( 295 print_preview.AppState.Field.IS_HEADER_FOOTER_ENABLED)); 296 } 297 if (this.appState_.hasField( 298 print_preview.AppState.Field.IS_LANDSCAPE_ENABLED)) { 299 this.landscape_.updateValue(this.appState_.getField( 300 print_preview.AppState.Field.IS_LANDSCAPE_ENABLED)); 301 } 302 if (this.appState_.hasField( 303 print_preview.AppState.Field.IS_COLLATE_ENABLED)) { 304 this.collate_.updateValue(this.appState_.getField( 305 print_preview.AppState.Field.IS_COLLATE_ENABLED)); 306 } 307 if (this.appState_.hasField( 308 print_preview.AppState.Field.IS_CSS_BACKGROUND_ENABLED)) { 309 this.cssBackground_.updateValue(this.appState_.getField( 310 print_preview.AppState.Field.IS_CSS_BACKGROUND_ENABLED)); 311 } 312 }, 313 314 /** 315 * @return {boolean} {@code true} if the stored print ticket is valid, 316 * {@code false} otherwise. 317 */ 318 isTicketValid: function() { 319 return this.isTicketValidForPreview() && 320 (!this.pageRange_.isCapabilityAvailable() || 321 this.pageRange_.isValid()); 322 }, 323 324 /** @return {boolean} Whether the ticket is valid for preview generation. */ 325 isTicketValidForPreview: function() { 326 return (!this.copies.isCapabilityAvailable() || this.copies.isValid()) && 327 (!this.marginsType_.isCapabilityAvailable() || 328 !this.marginsType_.isValueEqual( 329 print_preview.ticket_items.MarginsType.Value.CUSTOM) || 330 this.customMargins_.isValid()); 331 }, 332 333 /** 334 * Adds event listeners for the print ticket store. 335 * @private 336 */ 337 addEventListeners_: function() { 338 this.tracker_.add( 339 this.destinationStore_, 340 print_preview.DestinationStore.EventType. 341 SELECTED_DESTINATION_CAPABILITIES_READY, 342 this.onSelectedDestinationCapabilitiesReady_.bind(this)); 343 // TODO(rltoscano): Print ticket store shouldn't be re-dispatching these 344 // events, the consumers of the print ticket store events should listen 345 // for the events from document info instead. Will move this when 346 // consumers are all migrated. 347 this.tracker_.add( 348 this.documentInfo_, 349 print_preview.DocumentInfo.EventType.CHANGE, 350 this.onDocumentInfoChange_.bind(this)); 351 }, 352 353 /** 354 * Called when the capabilities of the selected destination are ready. 355 * @private 356 */ 357 onSelectedDestinationCapabilitiesReady_: function() { 358 var caps = this.destinationStore_.selectedDestination.capabilities; 359 var isFirstUpdate = this.capabilitiesHolder_.get() == null; 360 this.capabilitiesHolder_.set(caps); 361 if (isFirstUpdate) { 362 this.isInitialized_ = true; 363 cr.dispatchSimpleEvent(this, PrintTicketStore.EventType.INITIALIZE); 364 } else { 365 // Reset user selection for certain ticket items. 366 this.customMargins_.updateValue(null); 367 368 if (this.marginsType_.getValue() == 369 print_preview.ticket_items.MarginsType.Value.CUSTOM) { 370 this.marginsType_.updateValue( 371 print_preview.ticket_items.MarginsType.Value.DEFAULT); 372 } 373 cr.dispatchSimpleEvent( 374 this, PrintTicketStore.EventType.CAPABILITIES_CHANGE); 375 } 376 }, 377 378 /** 379 * Called when document data model has changed. Dispatches a print ticket 380 * store event. 381 * @private 382 */ 383 onDocumentInfoChange_: function() { 384 cr.dispatchSimpleEvent(this, PrintTicketStore.EventType.DOCUMENT_CHANGE); 385 }, 386 }; 387 388 // Export 389 return { 390 PrintTicketStore: PrintTicketStore 391 }; 392}); 393