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 cr.define('print_preview', function() { |
| 6 'use strict'; |
| 7 |
| 8 /** |
| 9 * Interface to the Chromium print preview generator. |
| 10 * @param {!print_preview.DestinationStore} destinationStore Used to get the |
| 11 * currently selected destination. |
| 12 * @param {!print_preview.PrintTicketStore} printTicketStore Used to read the |
| 13 * state of the ticket and write document information. |
| 14 * @param {!print_preview.NativeLayer} nativeLayer Used to communicate to |
| 15 * Chromium's preview rendering system. |
| 16 * @constructor |
| 17 * @extends {cr.EventTarget} |
| 18 */ |
| 19 function PreviewGenerator(destinationStore, printTicketStore, nativeLayer) { |
| 20 cr.EventTarget.call(this); |
| 21 |
| 22 /** |
| 23 * Used to get the currently selected destination. |
| 24 * @type {!print_preview.DestinationStore} |
| 25 * @private |
| 26 */ |
| 27 this.destinationStore_ = destinationStore; |
| 28 |
| 29 /** |
| 30 * Used to read the state of the ticket and write document information. |
| 31 * @type {!print_preview.PrintTicketStore} |
| 32 * @private |
| 33 */ |
| 34 this.printTicketStore_ = printTicketStore; |
| 35 |
| 36 /** |
| 37 * Interface to the Chromium native layer. |
| 38 * @type {!print_preview.NativeLayer} |
| 39 * @private |
| 40 */ |
| 41 this.nativeLayer_ = nativeLayer; |
| 42 |
| 43 /** |
| 44 * ID of current in-flight request. Requests that do not share this ID will |
| 45 * be ignored. |
| 46 * @type {number} |
| 47 * @private |
| 48 */ |
| 49 this.inFlightRequestId_ = -1; |
| 50 |
| 51 /** |
| 52 * Whether the previews are being generated in landscape mode. |
| 53 * @type {boolean} |
| 54 * @private |
| 55 */ |
| 56 this.isLandscapeEnabled_ = false; |
| 57 |
| 58 /** |
| 59 * Whether the previews are being generated with a header and footer. |
| 60 * @type {boolean} |
| 61 * @private |
| 62 */ |
| 63 this.isHeaderFooterEnabled_ = false; |
| 64 |
| 65 /** |
| 66 * Whether the previews are being generated in color. |
| 67 * @type {boolean} |
| 68 * @private |
| 69 */ |
| 70 this.isColorEnabled_ = false; |
| 71 |
| 72 /** |
| 73 * Whether the document should be fitted to the page. |
| 74 * @type {boolean} |
| 75 * @private |
| 76 */ |
| 77 this.isFitToPageEnabled_ = false; |
| 78 |
| 79 /** |
| 80 * Page number set used to generate the last preview. |
| 81 * @type {print_preview.PageNumberSet} |
| 82 * @private |
| 83 */ |
| 84 this.pageNumberSet_ = null; |
| 85 |
| 86 /** |
| 87 * Margins type used to generate the last preview. |
| 88 * @type {print_preview.ticket_items.MarginsType.Value} |
| 89 * @private |
| 90 */ |
| 91 this.marginsType_ = print_preview.ticket_items.MarginsType.Value.DEFAULT; |
| 92 |
| 93 /** |
| 94 * Custom margins used to generate the last preview. |
| 95 * @type {print_preview.Margins} |
| 96 * @private |
| 97 */ |
| 98 this.customMargins_ = null; |
| 99 |
| 100 /** |
| 101 * Destination that was selected for the last preview. |
| 102 * @type {print_preview.Destination} |
| 103 * @private |
| 104 */ |
| 105 this.selectedDestination_ = null; |
| 106 |
| 107 /** |
| 108 * Event tracker used to keep track of native layer events. |
| 109 * @type {!EventTracker} |
| 110 * @private |
| 111 */ |
| 112 this.tracker_ = new EventTracker(); |
| 113 |
| 114 this.addEventListeners_(); |
| 115 }; |
| 116 |
| 117 /** |
| 118 * Event types dispatched by the preview generator. |
| 119 * @enum {string} |
| 120 */ |
| 121 PreviewGenerator.EventType = { |
| 122 // Dispatched when the document can be printed. |
| 123 DOCUMENT_READY: 'print_preview.PreviewGenerator.DOCUMENT_READY', |
| 124 |
| 125 // Dispatched when a page preview is ready. The previewIndex field of the |
| 126 // event is the index of the page in the modified document, not the |
| 127 // original. So page 4 of the original document might be previewIndex = 0 of |
| 128 // the modified document. |
| 129 PAGE_READY: 'print_preview.PreviewGenerator.PAGE_READY', |
| 130 |
| 131 // Dispatched when the document preview starts to be generated. |
| 132 PREVIEW_START: 'print_preview.PreviewGenerator.PREVIEW_START', |
| 133 |
| 134 // Dispatched when the current print preview request fails. |
| 135 FAIL: 'print_preview.PreviewGenerator.FAIL' |
| 136 }; |
| 137 |
| 138 PreviewGenerator.prototype = { |
| 139 __proto__: cr.EventTarget.prototype, |
| 140 |
| 141 /** |
| 142 * Request that new preview be generated. A preview request will not be |
| 143 * generated if the print ticket has not changed sufficiently. |
| 144 * @return {boolean} Whether a new preview was actually requested. |
| 145 */ |
| 146 requestPreview: function() { |
| 147 if (!this.printTicketStore_.isTicketValid()) { |
| 148 throw Error('Requesting preview generation with invalid print ticket'); |
| 149 } |
| 150 if (!this.hasPreviewChanged_()) { |
| 151 // Changes to these ticket items might not trigger a new preview, but |
| 152 // they still need to be recorded. |
| 153 this.marginsType_ = this.printTicketStore_.getMarginsType(); |
| 154 this.customMargins_ = this.printTicketStore_.getCustomMargins(); |
| 155 return false; |
| 156 } |
| 157 this.isLandscapeEnabled_ = this.printTicketStore_.isLandscapeEnabled(); |
| 158 this.isHeaderFooterEnabled_ = |
| 159 this.printTicketStore_.isHeaderFooterEnabled(); |
| 160 this.isColorEnabled_ = this.printTicketStore_.isColorEnabled(); |
| 161 this.isFitToPageEnabled_ = this.printTicketStore_.isFitToPageEnabled(); |
| 162 this.pageNumberSet_ = this.printTicketStore_.getPageNumberSet(); |
| 163 this.marginsType_ = this.printTicketStore_.getMarginsType(); |
| 164 this.customMargins_ = this.printTicketStore_.getCustomMargins(); |
| 165 this.selectedDestination_ = this.destinationStore_.selectedDestination; |
| 166 |
| 167 this.inFlightRequestId_++; |
| 168 this.nativeLayer_.startGetPreview( |
| 169 this.destinationStore_.selectedDestination, |
| 170 this.printTicketStore_, |
| 171 this.inFlightRequestId_); |
| 172 return true; |
| 173 }, |
| 174 |
| 175 /** Removes all event listeners that the preview generator has attached. */ |
| 176 removeEventListeners: function() { |
| 177 this.tracker_.removeAll(); |
| 178 }, |
| 179 |
| 180 /** |
| 181 * Adds event listeners to the relevant native layer events. |
| 182 * @private |
| 183 */ |
| 184 addEventListeners_: function() { |
| 185 this.tracker_.add( |
| 186 this.nativeLayer_, |
| 187 print_preview.NativeLayer.EventType.PAGE_LAYOUT_READY, |
| 188 this.onPageLayoutReady_.bind(this)); |
| 189 this.tracker_.add( |
| 190 this.nativeLayer_, |
| 191 print_preview.NativeLayer.EventType.PAGE_COUNT_READY, |
| 192 this.onPageCountReady_.bind(this)); |
| 193 this.tracker_.add( |
| 194 this.nativeLayer_, |
| 195 print_preview.NativeLayer.EventType.PREVIEW_RELOAD, |
| 196 this.onPreviewReload_.bind(this)); |
| 197 this.tracker_.add( |
| 198 this.nativeLayer_, |
| 199 print_preview.NativeLayer.EventType.PAGE_PREVIEW_READY, |
| 200 this.onPagePreviewReady_.bind(this)); |
| 201 this.tracker_.add( |
| 202 this.nativeLayer_, |
| 203 print_preview.NativeLayer.EventType.PREVIEW_GENERATION_DONE, |
| 204 this.onPreviewGenerationDone_.bind(this)); |
| 205 this.tracker_.add( |
| 206 this.nativeLayer_, |
| 207 print_preview.NativeLayer.EventType.PREVIEW_GENERATION_FAIL, |
| 208 this.onPreviewGenerationFail_.bind(this)); |
| 209 }, |
| 210 |
| 211 /** |
| 212 * Dispatches a PAGE_READY event to signal that a page preview is ready. |
| 213 * @param {number} previewIndex Index of the page with respect to the pages |
| 214 * shown in the preview. E.g an index of 0 is the first displayed page, |
| 215 * but not necessarily the first original document page. |
| 216 * @param {number} pageNumber Number of the page with respect to the |
| 217 * document. A value of 3 means it's the third page of the original |
| 218 * document. |
| 219 * @param {string} previewUid Unique identifier of the preview. |
| 220 * @private |
| 221 */ |
| 222 dispatchPageReadyEvent_: function(previewIndex, pageNumber, previewUid) { |
| 223 var pageGenEvent = new cr.Event(PreviewGenerator.EventType.PAGE_READY); |
| 224 pageGenEvent.previewIndex = previewIndex; |
| 225 pageGenEvent.previewUrl = |
| 226 'chrome://print/' + previewUid + '/' + (pageNumber - 1) + |
| 227 '/print.pdf'; |
| 228 this.dispatchEvent(pageGenEvent); |
| 229 }, |
| 230 |
| 231 /** |
| 232 * Dispatches a PREVIEW_START event. Signals that the preview should be |
| 233 * reloaded. |
| 234 * @param {string} previewUid Unique identifier of the preview. |
| 235 * @private |
| 236 */ |
| 237 dispatchPreviewStartEvent_: function(previewUid) { |
| 238 var previewStartEvent = new cr.Event( |
| 239 PreviewGenerator.EventType.PREVIEW_START); |
| 240 var index = -1; |
| 241 if (this.printTicketStore_.isDocumentModifiable) { |
| 242 index = 0; |
| 243 } |
| 244 previewStartEvent.previewUrl = |
| 245 'chrome://print/' + previewUid + '/' + index + '/print.pdf'; |
| 246 this.dispatchEvent(previewStartEvent); |
| 247 }, |
| 248 |
| 249 /** |
| 250 * @return {boolean} Whether the print ticket has changed sufficiently to |
| 251 * determine whether a new preview request should be issued. |
| 252 * @private |
| 253 */ |
| 254 hasPreviewChanged_: function() { |
| 255 var ticketStore = this.printTicketStore_; |
| 256 return this.inFlightRequestId_ == -1 || |
| 257 ticketStore.isLandscapeEnabled() != this.isLandscapeEnabled_ || |
| 258 ticketStore.isHeaderFooterEnabled() != this.isHeaderFooterEnabled_ || |
| 259 ticketStore.isColorEnabled() != this.isColorEnabled_ || |
| 260 ticketStore.isFitToPageEnabled() != this.isFitToPageEnabled_ || |
| 261 !ticketStore.getPageNumberSet().equals(this.pageNumberSet_) || |
| 262 (ticketStore.getMarginsType() != this.marginsType_ && |
| 263 ticketStore.getMarginsType() != |
| 264 print_preview.ticket_items.MarginsType.Value.CUSTOM) || |
| 265 (ticketStore.getMarginsType() == |
| 266 print_preview.ticket_items.MarginsType.Value.CUSTOM && |
| 267 !ticketStore.getCustomMargins().equals(this.customMargins_)) || |
| 268 (this.selectedDestination_ != |
| 269 this.destinationStore_.selectedDestination && |
| 270 (this.destinationStore_.selectedDestination.id == |
| 271 print_preview.Destination.GooglePromotedId.LOCAL_PDF || |
| 272 this.selectedDestination_.id == |
| 273 print_preview.Destination.GooglePromotedId.LOCAL_PDF)); |
| 274 }, |
| 275 |
| 276 /** |
| 277 * Called when the page layout of the document is ready. Always occurs |
| 278 * as a result of a preview request. |
| 279 * @param {cr.Event} event Contains layout info about the document. |
| 280 * @private |
| 281 */ |
| 282 onPageLayoutReady_: function(event) { |
| 283 // NOTE: A request ID is not specified, so assuming its for the current |
| 284 // in-flight request. |
| 285 |
| 286 var origin = new print_preview.Coordinate2d( |
| 287 event.pageLayout.printableAreaX, |
| 288 event.pageLayout.printableAreaY); |
| 289 var size = new print_preview.Size( |
| 290 event.pageLayout.printableAreaWidth, |
| 291 event.pageLayout.printableAreaHeight); |
| 292 |
| 293 var margins = new print_preview.Margins( |
| 294 Math.round(event.pageLayout.marginTop), |
| 295 Math.round(event.pageLayout.marginRight), |
| 296 Math.round(event.pageLayout.marginBottom), |
| 297 Math.round(event.pageLayout.marginLeft)); |
| 298 |
| 299 var o = print_preview.ticket_items.CustomMargins.Orientation; |
| 300 var pageSize = new print_preview.Size( |
| 301 event.pageLayout.contentWidth + |
| 302 margins.get(o.LEFT) + margins.get(o.RIGHT), |
| 303 event.pageLayout.contentHeight + |
| 304 margins.get(o.TOP) + margins.get(o.BOTTOM)); |
| 305 |
| 306 this.printTicketStore_.updateDocumentPageInfo( |
| 307 new print_preview.PrintableArea(origin, size), |
| 308 pageSize, |
| 309 event.hasCustomPageSizeStyle, |
| 310 margins); |
| 311 }, |
| 312 |
| 313 /** |
| 314 * Called when the document page count is received from the native layer. |
| 315 * Always occurs as a result of a preview request. |
| 316 * @param {cr.Event} event Contains the document's page count. |
| 317 * @private |
| 318 */ |
| 319 onPageCountReady_: function(event) { |
| 320 if (this.inFlightRequestId_ != event.previewResponseId) { |
| 321 return; // Ignore old response. |
| 322 } |
| 323 this.printTicketStore_.updatePageCount(event.pageCount); |
| 324 this.pageNumberSet_ = this.printTicketStore_.getPageNumberSet(); |
| 325 }, |
| 326 |
| 327 /** |
| 328 * Called when the print preview should be reloaded. |
| 329 * @param {cr.Event} event Contains the preview UID and request ID. |
| 330 * @private |
| 331 */ |
| 332 onPreviewReload_: function(event) { |
| 333 if (this.inFlightRequestId_ != event.previewResponseId) { |
| 334 return; // Ignore old response. |
| 335 } |
| 336 this.dispatchPreviewStartEvent_(event.previewUid); |
| 337 var pageNumberSet = this.printTicketStore_.getPageNumberSet(); |
| 338 for (var i = 0; i < pageNumberSet.size; i++) { |
| 339 var pageNumber = pageNumberSet.getPageNumberAt(i); |
| 340 this.dispatchPageReadyEvent_(i, pageNumber, event.previewUid); |
| 341 } |
| 342 cr.dispatchSimpleEvent(this, PreviewGenerator.EventType.DOCUMENT_READY); |
| 343 }, |
| 344 |
| 345 /** |
| 346 * Called when a page's preview has been generated. Dispatches a |
| 347 * PAGE_READY event. |
| 348 * @param {cr.Event} event Contains the page index and preview UID. |
| 349 * @private |
| 350 */ |
| 351 onPagePreviewReady_: function(event) { |
| 352 if (this.inFlightRequestId_ != event.previewResponseId) { |
| 353 return; // Ignore old response. |
| 354 } |
| 355 var pageNumber = event.pageIndex + 1; |
| 356 if (this.printTicketStore_.getPageNumberSet().hasPageNumber(pageNumber)) { |
| 357 var previewIndex = this.printTicketStore_.getPageNumberSet() |
| 358 .getPageNumberIndex(pageNumber); |
| 359 if (previewIndex == 0) { |
| 360 this.dispatchPreviewStartEvent_(event.previewUid); |
| 361 } |
| 362 this.dispatchPageReadyEvent_( |
| 363 previewIndex, pageNumber, event.previewUid); |
| 364 } |
| 365 }, |
| 366 |
| 367 /** |
| 368 * Called when the preview generation is complete. Dispatches a |
| 369 * DOCUMENT_READY event. |
| 370 * @param {cr.Event} event Contains the preview UID and response ID. |
| 371 * @private |
| 372 */ |
| 373 onPreviewGenerationDone_: function(event) { |
| 374 if (this.inFlightRequestId_ != event.previewResponseId) { |
| 375 return; // Ignore old response. |
| 376 } |
| 377 // Dispatch a PREVIEW_START event since non-modifiable documents don't |
| 378 // trigger PAGE_READY events. |
| 379 if (!this.printTicketStore_.isDocumentModifiable) { |
| 380 this.dispatchPreviewStartEvent_(event.previewUid); |
| 381 } |
| 382 cr.dispatchSimpleEvent(this, PreviewGenerator.EventType.DOCUMENT_READY); |
| 383 }, |
| 384 |
| 385 /** |
| 386 * Called when the preview generation fails. |
| 387 * @private |
| 388 */ |
| 389 onPreviewGenerationFail_: function() { |
| 390 // NOTE: No request ID is returned from Chromium so its assumed its the |
| 391 // current one. |
| 392 cr.dispatchSimpleEvent(this, PreviewGenerator.EventType.FAIL); |
| 393 } |
| 394 }; |
| 395 |
| 396 // Export |
| 397 return { |
| 398 PreviewGenerator: PreviewGenerator |
| 399 }; |
| 400 }); |
OLD | NEW |