| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // require: cr/ui/print_preview_cloud.js | 5 // TODO Might be a problem where might be in fetching destinations state, then |
| 6 // to file selection state, then cancel, which results in the fetching |
| 7 // destinations state being lost. |
| 8 |
| 9 // TODO Move data/* into print_preview.data namespace |
| 10 |
| 11 // TODO Handle case where cloud print is initial destination, but cloud print is |
| 12 // not enabled. |
| 6 | 13 |
| 7 var localStrings = new LocalStrings(); | 14 var localStrings = new LocalStrings(); |
| 8 | 15 |
| 9 // If useCloudPrint is true we attempt to connect to cloud print | 16 <include src="component.js"/> |
| 10 // and populate the list of printers with cloud print printers. | 17 |
| 11 var useCloudPrint = false; | 18 cr.define('print_preview', function() { |
| 12 | 19 'use strict'; |
| 13 // Store the last selected printer index. | 20 |
| 14 var lastSelectedPrinterIndex = 0; | 21 /** |
| 15 | 22 * Container class for Chromium's print preview. |
| 16 // Used to disable some printing options when the preview is not modifiable. | 23 * @constructor |
| 17 var previewModifiable = false; | 24 * @extends {print_preview.Component} |
| 18 | 25 */ |
| 19 // Used to identify whether the printing frame has specific page size style. | 26 function PrintPreview() { |
| 20 var hasPageSizeStyle = false; | 27 print_preview.Component.call(this); |
| 21 | 28 |
| 22 // Destination list special value constants. | 29 /** |
| 23 | 30 * Used to communicate with Chromium's print system. |
| 24 /** @const */ var MANAGE_CLOUD_PRINTERS = 'manageCloudPrinters'; | 31 * @type {!print_preview.NativeLayer} |
| 25 /** @const */ var MANAGE_LOCAL_PRINTERS = 'manageLocalPrinters'; | 32 * @private |
| 26 /** @const */ var SIGN_IN = 'signIn'; | 33 */ |
| 27 /** @const */ var PRINT_TO_PDF = 'Save as PDF'; | 34 this.nativeLayer_ = new print_preview.NativeLayer(); |
| 28 /** @const */ var PRINT_WITH_CLOUD_PRINT = 'printWithCloudPrint'; | 35 |
| 29 | 36 /** |
| 30 // State of the print preview settings. | 37 * Data store which holds print destinations. |
| 31 var printSettings = new PrintSettings(); | 38 * @type {!print_preview.DestinationStore} |
| 32 | 39 * @private |
| 33 // Print ready data index. | 40 */ |
| 34 /** @const */ var PRINT_READY_DATA_INDEX = -1; | 41 this.destinationStore_ = new print_preview.DestinationStore(); |
| 35 | 42 |
| 36 // The name of the default or last used printer. | 43 /** |
| 37 var defaultOrLastUsedPrinterName = ''; | 44 * Storage of the print ticket used to create the print job. |
| 38 | 45 * @type {!print_preview.PrintTicketStore} |
| 39 // True when a pending print preview request exists. | 46 * @private |
| 40 var hasPendingPreviewRequest = false; | 47 */ |
| 41 | 48 this.printTicketStore_ = new print_preview.PrintTicketStore( |
| 42 // True when the first page is loaded in the plugin. | 49 this.destinationStore_); |
| 43 var isFirstPageLoaded = false; | 50 |
| 44 | 51 /** |
| 45 // The ID of the last preview request. | 52 * Holds the print and cancel buttons and renders some document statistics. |
| 46 var lastPreviewRequestID = -1; | 53 * @type {!print_preview.PrintHeader} |
| 47 | 54 * @private |
| 48 // The ID of the initial preview request. | 55 */ |
| 49 var initialPreviewRequestID = -1; | 56 this.printHeader_ = new print_preview.PrintHeader( |
| 50 | 57 this.printTicketStore_, this.destinationStore_); |
| 51 // True when a pending print file request exists. | 58 this.addChild(this.printHeader_); |
| 52 var hasPendingPrintDocumentRequest = false; | 59 |
| 53 | 60 /** |
| 54 // True when the complete metafile for the previewed doc is ready. | 61 * Component that renders the print destination. |
| 55 var isPrintReadyMetafileReady = false; | 62 * @type {!print_preview.DestinationSettings} |
| 56 | 63 * @private |
| 57 // True when preview tab is hidden. | 64 */ |
| 58 var isTabHidden = false; | 65 this.destinationSettings_ = new print_preview.DestinationSettings( |
| 59 | 66 this.destinationStore_); |
| 60 // True in kiosk mode where print preview can print automatically without | 67 this.addChild(this.destinationSettings_); |
| 61 // user intervention. See http://crbug.com/31395. | 68 |
| 62 var printAutomaticallyInKioskMode = false; | 69 /** |
| 63 | 70 * Component that renders UI for entering in page range. |
| 64 // @type {print_preview.PrintHeader} Holds the print and cancel buttons. | 71 * @type {!print_preview.PageSettings} |
| 65 var printHeader; | 72 * @private |
| 66 | 73 */ |
| 67 // @type {print_preview.PageSettings} Holds all the pages related settings. | 74 this.pageSettings_ = new print_preview.PageSettings(this.printTicketStore_); |
| 68 var pageSettings; | 75 this.addChild(this.pageSettings_); |
| 69 | 76 |
| 70 // @type {print_preview.CopiesSettings} Holds all the copies related settings. | 77 /** |
| 71 var copiesSettings; | 78 * Component that renders the copies settings. |
| 72 | 79 * @type {!print_preview.CopiesSettings} |
| 73 // @type {print_preview.LayoutSettings} Holds all the layout related settings. | 80 * @private |
| 74 var layoutSettings; | 81 */ |
| 75 | 82 this.copiesSettings_ = new print_preview.CopiesSettings( |
| 76 // @type {print_preview.MarginSettings} Holds all the margin related settings. | 83 this.printTicketStore_); |
| 77 var marginSettings; | 84 this.addChild(this.copiesSettings_); |
| 78 | 85 |
| 79 // @type {print_preview.HeaderFooterSettings} Holds all the header footer | 86 /** |
| 80 // related settings. | 87 * Component that renders the layout settings. |
| 81 var headerFooterSettings; | 88 * @type {!print_preview.LayoutSettings} |
| 82 | 89 * @private |
| 83 // @type {print_preview.ColorSettings} Holds all the color related settings. | 90 */ |
| 84 var colorSettings; | 91 this.layoutSettings_ = new print_preview.LayoutSettings( |
| 85 | 92 this.printTicketStore_); |
| 86 // @type {print_preview.PreviewArea} Holds information related to the preview | 93 this.addChild(this.layoutSettings_); |
| 87 // area (on the right). | 94 |
| 88 var previewArea; | 95 /** |
| 89 | 96 * Component that renders the color options. |
| 90 // True if the user has click 'Advanced...' in order to open the system print | 97 * @type {!print_preview.ColorSettings} |
| 91 // dialog. | 98 * @private |
| 92 var showingSystemDialog = false; | 99 */ |
| 93 | 100 this.colorSettings_ = new print_preview.ColorSettings( |
| 94 // True if the user has clicked 'Open PDF in Preview' option. | 101 this.printTicketStore_); |
| 95 var previewAppRequested = false; | 102 this.addChild(this.colorSettings_); |
| 96 | 103 |
| 97 // The range of options in the printer dropdown controlled by cloud print. | 104 /** |
| 98 var firstCloudPrintOptionPos = 0; | 105 * Component that renders a select box for choosing margin settings. |
| 99 var lastCloudPrintOptionPos = firstCloudPrintOptionPos; | 106 * @type {!print_preview.MarginSettings} |
| 100 | 107 * @private |
| 101 // Store the current previewUid. | 108 */ |
| 102 var currentPreviewUid = ''; | 109 this.marginSettings_ = new print_preview.MarginSettings( |
| 103 | 110 this.printTicketStore_); |
| 104 // True if we need to generate draft preview data. | 111 this.addChild(this.marginSettings_); |
| 105 var generateDraftData = true; | 112 |
| 106 | 113 /** |
| 107 // The last element clicked with the mouse. | 114 * Holds all the header footer related settings. |
| 108 var lastClickedElement = null; | 115 * @type {!print_preview.HeaderFooterSettings} |
| 109 | 116 * @private |
| 110 // A dictionary of cloud printers that have been added to the printer | 117 */ |
| 111 // dropdown. | 118 this.headerFooterSettings_ = new print_preview.HeaderFooterSettings( |
| 112 var addedCloudPrinters = {}; | 119 this.printTicketStore_); |
| 113 | 120 this.addChild(this.headerFooterSettings_); |
| 114 // The maximum number of cloud printers to allow in the dropdown. | 121 |
| 115 /** @const */ var maxCloudPrinters = 10; | 122 /** |
| 116 | 123 * Area of the UI that holds the print preview. |
| 117 /** @const */ var MIN_REQUEST_ID = 0; | 124 * @type {!print_preview.PreviewArea} |
| 118 /** @const */ var MAX_REQUEST_ID = 32000; | 125 * @private |
| 119 | 126 */ |
| 120 // Names of all the custom events used. | 127 this.previewArea_ = new print_preview.PreviewArea( |
| 121 var customEvents = { | 128 this.destinationStore_, this.printTicketStore_, this.nativeLayer_); |
| 122 // Fired when the mouse moves while a margin line is being dragged. | 129 this.addChild(this.previewArea_); |
| 123 MARGIN_LINE_DRAG: 'marginLineDrag', | 130 |
| 124 // Fired when a mousedown event occurs on a margin line. | 131 /** |
| 125 MARGIN_LINE_MOUSE_DOWN: 'marginLineMouseDown', | 132 * Interface to the Google Cloud Print API. Null if Google Cloud Print |
| 126 // Fired when a margin textbox gains focus. | 133 * integration is disabled. |
| 127 MARGIN_TEXTBOX_FOCUSED: 'marginTextboxFocused', | 134 * @type {cloudprint.CloudPrintInterface} |
| 128 // Fired when a new preview might be needed because of margin changes. | 135 * @private |
| 129 MARGINS_MAY_HAVE_CHANGED: 'marginsMayHaveChanged', | 136 */ |
| 130 // Fired when a pdf generation related error occurs. | 137 this.cloudPrintInterface_ = null; |
| 131 PDF_GENERATION_ERROR: 'PDFGenerationError', | 138 |
| 132 // Fired once the first page of the pdf document is loaded in the plugin. | 139 /** |
| 133 PDF_LOADED: 'PDFLoaded', | 140 * Whether in kiosk mode where print preview can print automatically without |
| 134 // Fired when the selected printer capabilities change. | 141 * user intervention. See http://crbug.com/31395. Print will start when |
| 135 PRINTER_CAPABILITIES_UPDATED: 'printerCapabilitiesUpdated', | 142 * both the print ticket has been initialized, and an initial printer has |
| 136 // Fired when the print button needs to be updated. | 143 * been selected. |
| 137 UPDATE_PRINT_BUTTON: 'updatePrintButton', | 144 * @type {boolean} |
| 138 // Fired when the print summary needs to be updated. | 145 * @private |
| 139 UPDATE_SUMMARY: 'updateSummary' | 146 */ |
| 140 }; | 147 this.isInKioskAutoPrintMode_ = false; |
| 141 | 148 |
| 142 /** | 149 /** |
| 143 * Window onload handler, sets up the page and starts print preview by getting | 150 * State of the print preview UI. |
| 144 * the printer list. | 151 * @type {print_preview.PrintPreview.UiState_} |
| 145 */ | 152 * @private |
| 146 function onLoad() { | 153 */ |
| 147 initialPreviewRequestID = randomInteger(MIN_REQUEST_ID, MAX_REQUEST_ID); | 154 this.uiState_ = PrintPreview.UiState_.INITIALIZING; |
| 148 lastPreviewRequestID = initialPreviewRequestID; | 155 |
| 149 | 156 /** |
| 150 previewArea = print_preview.PreviewArea.getInstance(); | 157 * Current state of fetching destinations. |
| 151 printHeader = print_preview.PrintHeader.getInstance(); | 158 * @type {print_preview.PrintPreview.FetchState_} |
| 152 document.addEventListener(customEvents.PDF_GENERATION_ERROR, | 159 * @private |
| 153 cancelPendingPrintRequest); | 160 */ |
| 154 document.addEventListener('click', setLastClickedElement); | 161 this.fetchState_ = PrintPreview.FetchState_.READY; |
| 155 | 162 |
| 156 if (!checkCompatiblePluginExists()) { | 163 /** |
| 157 disableInputElementsInSidebar(); | 164 * Whether document preview generation is in progress. |
| 158 $('cancel-button').focus(); | 165 * @type {boolean} |
| 159 previewArea.displayErrorMessageWithButtonAndNotify( | 166 * @private |
| 160 localStrings.getString('noPlugin'), | 167 */ |
| 161 localStrings.getString('launchNativeDialog'), | 168 this.isPreviewGenerationInProgress_ = true; |
| 162 launchNativePrintDialog); | 169 |
| 163 $('mainview').parentElement.removeChild($('dummy-viewer')); | 170 this.tracker.add(window, 'DOMContentLoaded', this.onWindowLoad_.bind(this)); |
| 164 return; | 171 }; |
| 165 } | 172 |
| 166 | 173 /** |
| 167 $('system-dialog-link').addEventListener('click', onSystemDialogLinkClicked); | 174 * States of the print preview. |
| 168 if (cr.isMac) { | 175 * @enum {string} |
| 169 $('open-pdf-in-preview-link').addEventListener( | 176 * @private |
| 170 'click', onOpenPdfInPreviewLinkClicked); | 177 */ |
| 171 } | 178 PrintPreview.UiState_ = { |
| 172 $('mainview').parentElement.removeChild($('dummy-viewer')); | 179 INITIALIZING: 'initializing', |
| 173 | 180 READY: 'ready', |
| 174 $('printer-list').disabled = true; | 181 OPENING_PDF_PREVIEW: 'opening-pdf-preview', |
| 175 | 182 OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog', |
| 176 pageSettings = print_preview.PageSettings.getInstance(); | 183 PRINTING: 'printing', |
| 177 copiesSettings = print_preview.CopiesSettings.getInstance(); | 184 FILE_SELECTION: 'file-selection', |
| 178 layoutSettings = print_preview.LayoutSettings.getInstance(); | 185 CLOSING: 'closing', |
| 179 marginSettings = print_preview.MarginSettings.getInstance(); | 186 ERROR: 'error' |
| 180 headerFooterSettings = print_preview.HeaderFooterSettings.getInstance(); | 187 }; |
| 181 colorSettings = print_preview.ColorSettings.getInstance(); | 188 |
| 182 $('printer-list').onchange = updateControlsWithSelectedPrinterCapabilities; | 189 /** |
| 183 | 190 * Bitfield of the states of fetching destinations. |
| 184 previewArea.showLoadingAnimation(); | 191 * @enum {number} |
| 185 chrome.send('getInitialSettings'); | 192 * @private |
| 186 } | 193 */ |
| 187 | 194 PrintPreview.FetchState_ = { |
| 188 /** | 195 READY: 1, |
| 189 * @param {object} initialSettings An object containing all the initial | 196 LOCAL_DESTINATIONS: 2, |
| 190 * settings. | 197 RECENT_CLOUD_DESTINATIONS: 4, |
| 191 */ | 198 ALL_CLOUD_DESTINATIONS: 8 |
| 192 function setInitialSettings(initialSettings) { | 199 }; |
| 193 setInitiatorTabTitle(initialSettings['initiatorTabTitle']); | 200 |
| 194 previewModifiable = initialSettings['previewModifiable']; | 201 PrintPreview.prototype = { |
| 195 if (previewModifiable) { | 202 __proto__: print_preview.Component.prototype, |
| 196 print_preview.MarginSettings.setNumberFormatAndMeasurementSystem( | 203 |
| 197 initialSettings['numberFormat'], | 204 /** @override */ |
| 198 initialSettings['measurementSystem']); | 205 decorateInternal: function() { |
| 199 marginSettings.setLastUsedMargins(initialSettings); | 206 this.printHeader_.decorate($('print-header')); |
| 200 } | 207 this.destinationSettings_.decorate($('destination-settings')); |
| 201 printAutomaticallyInKioskMode = | 208 this.pageSettings_.decorate($('page-settings')); |
| 202 initialSettings['printAutomaticallyInKioskMode']; | 209 this.copiesSettings_.decorate($('copies-settings')); |
| 203 headerFooterSettings.setChecked(initialSettings['headerFooterEnabled']); | 210 this.layoutSettings_.decorate($('layout-settings')); |
| 204 copiesSettings.previousDuplexMode = initialSettings['duplex']; | 211 this.colorSettings_.decorate($('color-settings')); |
| 205 setDefaultPrinter(initialSettings['printerName'], | 212 this.marginSettings_.decorate($('margin-settings')); |
| 206 initialSettings['cloudPrintData']); | 213 this.headerFooterSettings_.decorate($('header-footer-settings')); |
| 207 } | 214 this.previewArea_.decorate($('preview-area')); |
| 208 | 215 |
| 209 /** | 216 setIsVisible($('cloud-print-dialog-link'), cr.isChromeOS); |
| 210 * Disables the input elements in the sidebar. | 217 setIsVisible($('system-dialog-link'), !cr.isChromeOS); |
| 211 */ | 218 setIsVisible($('open-pdf-in-preview-link'), cr.isMac); |
| 212 function disableInputElementsInSidebar() { | 219 }, |
| 213 var els = $('navbar-container').querySelectorAll('input, button, select'); | 220 |
| 214 for (var i = 0; i < els.length; i++) { | 221 /** @override */ |
| 215 if (els[i] == printHeader.cancelButton) | 222 enterDocument: function() { |
| 216 continue; | 223 // Native layer events. |
| 217 els[i].disabled = true; | 224 this.tracker.add( |
| 218 } | 225 this.nativeLayer_, |
| 219 } | 226 print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET, |
| 220 | 227 this.onInitialSettingsSet_.bind(this)); |
| 221 /** | 228 this.tracker.add( |
| 222 * Enables the input elements in the sidebar. | 229 this.nativeLayer_, |
| 223 */ | 230 print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE, |
| 224 function enableInputElementsInSidebar() { | 231 this.onCloudPrintEnable_.bind(this)); |
| 225 var els = $('navbar-container').querySelectorAll('input, button, select'); | 232 this.tracker.add( |
| 226 for (var i = 0; i < els.length; i++) | 233 this.nativeLayer_, |
| 227 els[i].disabled = false; | 234 print_preview.NativeLayer.EventType.LOCAL_DESTINATIONS_SET, |
| 228 } | 235 this.onLocalDestinationsSet_.bind(this)); |
| 229 | 236 this.tracker.add( |
| 230 /** | 237 this.nativeLayer_, |
| 231 * Keep track of the last element to receive a click. | 238 print_preview.NativeLayer.EventType.CAPABILITIES_SET, |
| 232 * @param {Event} e The click event. | 239 this.onLocalDestinationCapabilitiesSet_.bind(this)); |
| 233 */ | 240 this.tracker.add( |
| 234 function setLastClickedElement(e) { | 241 this.nativeLayer_, |
| 235 lastClickedElement = e.target; | 242 print_preview.NativeLayer.EventType.DESTINATIONS_RELOAD, |
| 236 } | 243 this.onDestinationsReload_.bind(this)); |
| 237 | 244 this.tracker.add( |
| 238 /** | 245 this.nativeLayer_, |
| 239 * Disables the controls in the sidebar, shows the throbber and instructs the | 246 print_preview.NativeLayer.EventType.PRINT_TO_CLOUD, |
| 240 * backend to open the native print dialog. | 247 this.onPrintToCloud_.bind(this)); |
| 241 */ | 248 this.tracker.add( |
| 242 function onSystemDialogLinkClicked() { | 249 this.nativeLayer_, |
| 243 if (showingSystemDialog) | 250 print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL, |
| 244 return; | 251 this.onFileSelectionCancel_.bind(this)); |
| 245 showingSystemDialog = true; | 252 this.tracker.add( |
| 246 disableInputElementsInSidebar(); | 253 this.nativeLayer_, |
| 247 printHeader.disableCancelButton(); | 254 print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE, |
| 248 $('system-dialog-throbber').hidden = false; | 255 this.onFileSelectionComplete_.bind(this)); |
| 249 chrome.send('showSystemDialog'); | 256 this.tracker.add( |
| 250 } | 257 this.nativeLayer_, |
| 251 | 258 print_preview.NativeLayer.EventType.SETTINGS_INVALID, |
| 252 /** | 259 this.onSettingsInvalid_.bind(this)); |
| 253 * Disables the controls in the sidebar, shows the throbber and instructs the | 260 |
| 254 * backend to open the pdf in native preview app. This is only for Mac. | 261 this.tracker.add( |
| 255 */ | 262 $('system-dialog-link'), |
| 256 function onOpenPdfInPreviewLinkClicked() { | 263 'click', |
| 257 if (previewAppRequested) | 264 this.onSystemDialogLinkClicked_.bind(this)); |
| 258 return; | 265 this.tracker.add( |
| 259 previewAppRequested = true; | 266 $('cloud-print-dialog-link'), |
| 260 disableInputElementsInSidebar(); | 267 'click', |
| 261 $('open-preview-app-throbber').hidden = false; | 268 this.onSystemDialogLinkClicked_.bind(this)); |
| 262 printHeader.disableCancelButton(); | 269 this.tracker.add( |
| 263 requestToPrintDocument(); | 270 $('open-pdf-in-preview-link'), |
| 264 } | 271 'click', |
| 265 | 272 this.onOpenPdfInPreviewLinkClick_.bind(this)); |
| 266 /** | 273 |
| 267 * Similar to onSystemDialogLinkClicked(), but specific to the | 274 this.tracker.add( |
| 268 * 'Launch native print dialog' UI. | 275 this.previewArea_, |
| 269 */ | 276 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS, |
| 270 function launchNativePrintDialog() { | 277 this.onPreviewGenerationInProgress_.bind(this)); |
| 271 if (showingSystemDialog) | 278 this.tracker.add( |
| 272 return; | 279 this.previewArea_, |
| 273 showingSystemDialog = true; | 280 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE, |
| 274 previewArea.errorButton.disabled = true; | 281 this.onPreviewGenerationDone_.bind(this)); |
| 275 printHeader.disableCancelButton(); | 282 this.tracker.add( |
| 276 $('native-print-dialog-throbber').hidden = false; | 283 this.previewArea_, |
| 277 chrome.send('showSystemDialog'); | 284 print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL, |
| 278 } | 285 this.onPreviewGenerationFail_.bind(this)); |
| 279 | 286 this.tracker.add( |
| 280 /** | 287 this.previewArea_, |
| 281 * Gets the selected printer capabilities and updates the controls accordingly. | 288 print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK, |
| 282 */ | 289 this.openSystemPrintDialog_.bind(this)); |
| 283 function updateControlsWithSelectedPrinterCapabilities() { | 290 |
| 284 var printerList = $('printer-list'); | 291 this.tracker.add( |
| 285 var selectedIndex = printerList.selectedIndex; | 292 this.destinationStore_, |
| 286 if (selectedIndex < 0) | 293 print_preview.DestinationStore.EventType.DESTINATION_SELECT, |
| 287 return; | 294 this.onDestinationSelect_.bind(this)); |
| 288 if (cr.isMac) | 295 |
| 289 $('open-pdf-in-preview-link').disabled = false; | 296 this.tracker.add( |
| 290 | 297 this.printHeader_, |
| 291 var skip_refresh = false; | 298 print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK, |
| 292 var selectedValue = printerList.options[selectedIndex].value; | 299 this.onPrintButtonClick_.bind(this)); |
| 293 if (cloudprint.isCloudPrint(printerList.options[selectedIndex])) { | 300 this.tracker.add( |
| 294 cloudprint.updatePrinterCaps(printerList.options[selectedIndex], | 301 this.printHeader_, |
| 295 doUpdateCloudPrinterCapabilities); | 302 print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK, |
| 296 skip_refresh = true; | 303 this.onCancelButtonClick_.bind(this)); |
| 297 } else if (selectedValue == SIGN_IN || | 304 |
| 298 selectedValue == MANAGE_CLOUD_PRINTERS || | 305 this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this)); |
| 299 selectedValue == MANAGE_LOCAL_PRINTERS) { | 306 }, |
| 300 printerList.selectedIndex = lastSelectedPrinterIndex; | 307 |
| 301 chrome.send(selectedValue); | 308 /** |
| 302 skip_refresh = true; | 309 * Disables all of the controls within the print preview. |
| 303 } else if (selectedValue == PRINT_TO_PDF || | 310 * @private |
| 304 selectedValue == PRINT_WITH_CLOUD_PRINT) { | 311 */ |
| 305 updateWithPrinterCapabilities({ | 312 disable_: function() { |
| 306 'disableColorOption': true, | 313 $('system-dialog-link').disabled = true; |
| 307 'setColorAsDefault': true, | 314 $('cloud-print-dialog-link').disabled = true; |
| 308 'setDuplexAsDefault': false, | 315 $('open-pdf-in-preview-link').disabled = true; |
| 309 'printerColorModelForColor': print_preview.ColorSettings.COLOR, | 316 this.printHeader_.isEnabled = false; |
| 310 'printerDefaultDuplexValue': copiesSettings.UNKNOWN_DUPLEX_MODE, | 317 this.destinationSettings_.isEnabled = false; |
| 311 'disableCopiesOption': true}); | 318 this.pageSettings_.isEnabled = false; |
| 312 if (cr.isChromeOS && selectedValue == PRINT_WITH_CLOUD_PRINT) | 319 this.copiesSettings_.isEnabled = false; |
| 313 requestToPrintDocument(); | 320 this.layoutSettings_.isEnabled = false; |
| 314 } else { | 321 this.colorSettings_.isEnabled = false; |
| 315 // This message will call back to 'updateWithPrinterCapabilities' | 322 this.marginSettings_.isEnabled = false; |
| 316 // function. | 323 this.headerFooterSettings_.isEnabled = false; |
| 317 chrome.send('getPrinterCapabilities', [selectedValue]); | 324 }, |
| 318 } | 325 |
| 319 if (!skip_refresh) { | 326 /** |
| 320 lastSelectedPrinterIndex = selectedIndex; | 327 * Creates a local PDF print destination. |
| 321 | 328 * @return {!print_preview.Destination} Created print destination. |
| 322 // Regenerate the preview data based on selected printer settings. | 329 * @private |
| 323 // Do not reset the margins if no preview request has been made. | 330 */ |
| 324 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; | 331 createLocalPdfPrintDestination_: function() { |
| 325 setDefaultValuesAndRegeneratePreview(resetMargins); | 332 var dest = new print_preview.Destination( |
| 326 } | 333 print_preview.Destination.GooglePromotedId.LOCAL_PDF, |
| 327 } | 334 localStrings.getString('printToPDF'), |
| 328 | 335 false /*isRecent*/, |
| 329 /** | 336 true /*isLocal*/); |
| 330 * Helper function to do the actual work of updating cloud printer | 337 dest.capabilities = new print_preview.ChromiumCapabilities( |
| 331 * capabilities. | 338 false /*hasCopiesCapability*/, |
| 332 * @param {Object} printer The printer object to set capabilities for. | 339 '1' /*defaultCopiesStr*/, |
| 333 */ | 340 false /*hasCollateCapability*/, |
| 334 function doUpdateCloudPrinterCapabilities(printer) { | 341 false /*defaultIsCollateEnabled*/, |
| 335 var settings = {'disableColorOption': !cloudprint.supportsColor(printer), | 342 false /*hasDuplexCapability*/, |
| 336 'setColorAsDefault': cloudprint.colorIsDefault(printer), | 343 false /*defaultIsDuplexEnabled*/, |
| 337 'disableCopiesOption': true, | 344 true /*hasOrientationCapability*/, |
| 338 'disableLandscapeOption': true}; | 345 false /*defaultIsLandscapeEnabled*/, |
| 339 updateWithPrinterCapabilities(settings); | 346 true /*hasColorCapability*/, |
| 340 var printerList = $('printer-list'); | 347 true /*defaultIsColorEnabled*/); |
| 341 var selectedIndex = printerList.selectedIndex; | 348 return dest; |
| 342 lastSelectedPrinterIndex = selectedIndex; | 349 }, |
| 343 | 350 |
| 344 // Regenerate the preview data based on selected printer settings. | 351 /** |
| 345 // Do not reset the margins if no preview request has been made. | 352 * Creates a new "Print with Cloud Print" print destination. NOTE: this |
| 346 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; | 353 * destination will appear as "Search for additional printers..." on |
| 347 setDefaultValuesAndRegeneratePreview(resetMargins); | 354 * Chrome OS. |
| 348 } | 355 * @return {!print_preview.Destination} Created print destination. |
| 349 | 356 * @private |
| 350 /** | 357 */ |
| 351 * Notifies listeners of |customEvents.PRINTER_CAPABILITIES_UPDATED| about the | 358 createPrintWithCloudPrintDestination_: function() { |
| 352 * capabilities of the currently selected printer. It is called from C++ too. | 359 var dest = new print_preview.Destination( |
| 353 * @param {Object} settingInfo printer setting information. | 360 print_preview.Destination.GooglePromotedId.PRINT_WITH_CLOUD_PRINT, |
| 354 */ | 361 localStrings.getString('printWithCloudPrint'), |
| 355 function updateWithPrinterCapabilities(settingInfo) { | 362 false /*isRecent*/, |
| 356 var customEvent = new cr.Event(customEvents.PRINTER_CAPABILITIES_UPDATED); | 363 false /*isLocal*/); |
| 357 customEvent.printerCapabilities = settingInfo; | 364 dest.capabilities = new print_preview.ChromiumCapabilities( |
| 358 document.dispatchEvent(customEvent); | 365 false /*hasCopiesCapability*/, |
| 359 } | 366 '1' /*defaultCopiesStr*/, |
| 360 | 367 false /*hasCollateCapability*/, |
| 361 /** | 368 false /*defaultIsCollateEnabled*/, |
| 362 * Reloads the printer list. | 369 false /*hasDuplexCapability*/, |
| 363 */ | 370 false /*defaultIsDuplexEnabled*/, |
| 364 function reloadPrintersList() { | 371 true /*hasOrientationCapability*/, |
| 365 $('printer-list').length = 0; | 372 false /*defaultIsLandscapeEnabled*/, |
| 366 firstCloudPrintOptionPos = 0; | 373 true /*hasColorCapability*/, |
| 367 lastCloudPrintOptionPos = 0; | 374 true /*defaultIsColorEnabled*/); |
| 368 chrome.send('getPrinters'); | 375 return dest; |
| 369 } | 376 }, |
| 370 | 377 |
| 371 /** | 378 /** |
| 372 * Turn on the integration of Cloud Print. | 379 * Prints the document or launches a pdf preview on the local system. |
| 373 * @param {string} cloudPrintURL The URL to use for cloud print servers. | 380 * @param {boolean} isPdfPreview Whether to launch the pdf preview. |
| 374 */ | 381 * @private |
| 375 function setUseCloudPrint(cloudPrintURL) { | 382 */ |
| 376 useCloudPrint = true; | 383 printDocumentOrOpenPdfPreview_: function(isPdfPreview) { |
| 377 cloudprint.setBaseURL(cloudPrintURL); | 384 if (this.uiState_ != PrintPreview.UiState_.READY) { |
| 378 } | 385 throw Error( |
| 379 | 386 'Print document request received when not in ready state: ' + |
| 380 /** | 387 this.uiState_); |
| 381 * Take the PDF data handed to us and submit it to the cloud, closing the print | 388 } |
| 382 * preview tab once the upload is successful. | 389 if (isPdfPreview) { |
| 383 * @param {string} data Data to send as the print job. | 390 this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW; |
| 384 */ | 391 } else if (this.destinationStore_.selectedDestination.isPrintToPdf) { |
| 385 function printToCloud(data) { | 392 this.uiState_ = PrintPreview.UiState_.FILE_SELECTION; |
| 386 cloudprint.printToCloud(data, finishedCloudPrinting); | 393 } else { |
| 387 } | 394 this.uiState_ = PrintPreview.UiState_.PRINTING; |
| 388 | 395 } |
| 389 /** | 396 if (this.printIfReady_() && |
| 390 * Cloud print upload of the PDF file is finished, time to close the dialog. | 397 this.destinationStore_.selectedDestination.isLocal && |
| 391 */ | 398 !this.destinationStore_.selectedDestination.isPrintToPdf) { |
| 392 function finishedCloudPrinting() { | 399 // Hide the dialog for now. The actual print command will be issued when |
| 393 closePrintPreviewTab(); | 400 // the preview generation is done. |
| 394 } | 401 this.nativeLayer_.startHideDialog(); |
| 395 | 402 } |
| 396 /** | 403 }, |
| 397 * Checks whether the specified settings are valid. | 404 |
| 398 * | 405 /** |
| 399 * @return {boolean} true if settings are valid, false if not. | 406 * Attempts to print if needed and if ready. |
| 400 */ | 407 * @return {boolean} Whether a print request was issued. |
| 401 function areSettingsValid() { | 408 * @private |
| 402 var selectedPrinter = getSelectedPrinterName(); | 409 */ |
| 403 return pageSettings.isPageSelectionValid() && | 410 printIfReady_: function() { |
| 404 marginSettings.areMarginSettingsValid() && | 411 if ((this.uiState_ == PrintPreview.UiState_.PRINTING || |
| 405 (copiesSettings.isValid() || selectedPrinter == PRINT_TO_PDF || | 412 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW || |
| 406 selectedPrinter == PRINT_WITH_CLOUD_PRINT); | 413 this.uiState_ == PrintPreview.UiState_.FILE_SELECTION || |
| 407 } | 414 this.isInKioskAutoPrintMode_) && |
| 408 | 415 !this.isPreviewGenerationInProgress_ && |
| 409 /** | 416 this.destinationStore_.selectedDestination && |
| 410 * Creates an object based on the values in the printer settings. | 417 this.destinationStore_.selectedDestination.capabilities) { |
| 411 * | 418 if (!this.printTicketStore_.isTicketValid()) { |
| 412 * @return {Object} Object containing print job settings. | 419 throw Error('Trying to print with invalid ticket'); |
| 413 */ | 420 } |
| 414 function getSettings() { | 421 this.nativeLayer_.startSaveDestinationAndTicket( |
| 415 var deviceName = getSelectedPrinterName(); | 422 this.destinationStore_.selectedDestination, |
| 416 var printToPDF = deviceName == PRINT_TO_PDF; | 423 this.printTicketStore_); |
| 417 var printWithCloudPrint = deviceName == PRINT_WITH_CLOUD_PRINT; | 424 this.nativeLayer_.startPrint( |
| 418 | 425 this.destinationStore_.selectedDestination, |
| 419 var settings = | 426 this.printTicketStore_, |
| 420 {'deviceName': deviceName, | 427 this.cloudPrintInterface_); |
| 421 'pageRange': pageSettings.selectedPageRanges, | 428 return true; |
| 422 'duplex': copiesSettings.duplexMode, | 429 } else { |
| 423 'copies': copiesSettings.numberOfCopies, | 430 return false; |
| 424 'collate': copiesSettings.isCollated(), | 431 } |
| 425 'landscape': layoutSettings.isLandscape(), | 432 }, |
| 426 'color': colorSettings.colorMode, | 433 |
| 427 'printToPDF': printToPDF, | 434 /** |
| 428 'printWithCloudPrint': printWithCloudPrint, | 435 * Closes the print preview. |
| 429 'isFirstRequest' : false, | 436 * @private |
| 430 'headerFooterEnabled': headerFooterSettings.hasHeaderFooter(), | 437 */ |
| 431 'marginsType': marginSettings.selectedMarginsValue, | 438 close_: function() { |
| 432 'requestID': -1, | 439 this.exitDocument(); |
| 433 'generateDraftData': generateDraftData, | 440 this.uiState_ = PrintPreview.UiState_.CLOSING; |
| 434 'previewModifiable': previewModifiable}; | 441 this.nativeLayer_.startCloseDialog(); |
| 435 | 442 }, |
| 436 if (marginSettings.isCustomMarginsSelected()) | 443 |
| 437 settings['marginsCustom'] = marginSettings.customMargins; | 444 /** |
| 438 | 445 * Opens the native system print dialog after disabling all controls. |
| 439 var printerList = $('printer-list'); | 446 * @private |
| 440 var selectedPrinter = printerList.selectedIndex; | 447 */ |
| 441 if (cloudprint.isCloudPrint(printerList.options[selectedPrinter])) { | 448 openSystemPrintDialog_: function() { |
| 442 settings['cloudPrintID'] = | 449 if (this.uiState_ != PrintPreview.UiState_.READY) { |
| 443 printerList.options[selectedPrinter].value; | 450 throw Error( |
| 444 } | 451 'Request to open system dialog received when not in ready state: ' + |
| 445 return settings; | 452 this.uiState_); |
| 446 } | 453 } |
| 447 | 454 this.disable_(); |
| 448 /** | 455 this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG; |
| 449 * Creates an object based on the values in the printer settings. | 456 this.nativeLayer_.startShowSystemDialog(); |
| 450 * Note: |lastPreviewRequestID| is being modified every time this function is | 457 }, |
| 451 * called. Only call this function when a preview request is actually sent, | 458 |
| 452 * otherwise (for example when debugging) call getSettings(). | 459 /** |
| 453 * | 460 * Window onload handler, sets up the page and starts print preview by |
| 454 * @return {Object} Object containing print job settings. | 461 * getting the printer list. |
| 455 */ | 462 * @private |
| 456 function getSettingsWithRequestID() { | 463 */ |
| 457 var settings = getSettings(); | 464 onWindowLoad_: function() { |
| 458 settings.requestID = generatePreviewRequestID(); | 465 this.decorate($('print-preview')); |
| 459 settings.isFirstRequest = isFirstPreviewRequest(); | 466 i18nTemplate.process(document, templateData); |
| 460 return settings; | 467 if (!this.previewArea_.hasCompatiblePlugin) { |
| 461 } | 468 this.disable_(); |
| 462 | 469 } |
| 463 /** | 470 this.nativeLayer_.startGetInitialSettings(); |
| 464 * @return {number} The next unused preview request id. | 471 }, |
| 465 */ | 472 |
| 466 function generatePreviewRequestID() { | 473 /** |
| 467 return ++lastPreviewRequestID; | 474 * Called when the native layer has initial settings to set. Sets the |
| 468 } | 475 * initial settings of the print preview and begins fetching print |
| 469 | 476 * destinations. |
| 470 /** | 477 * @param {cr.Event} event Contains the initial print preview settings |
| 471 * @return {boolean} True iff a preview has been requested. | 478 * persisted through the session. |
| 472 */ | 479 * @private |
| 473 function hasRequestedPreview() { | 480 */ |
| 474 return lastPreviewRequestID != initialPreviewRequestID; | 481 onInitialSettingsSet_: function(event) { |
| 475 } | 482 if (this.uiState_ != PrintPreview.UiState_.INITIALIZING) { |
| 476 | 483 throw Error( |
| 477 /** | 484 'Updating initial settings when not in initializing state: ' + |
| 478 * @return {boolean} True if |lastPreviewRequestID| corresponds to the initial | 485 this.uiState_); |
| 479 * preview request. | 486 } |
| 480 */ | 487 this.uiState_ = PrintPreview.UiState_.READY; |
| 481 function isFirstPreviewRequest() { | 488 |
| 482 return lastPreviewRequestID == initialPreviewRequestID + 1; | 489 this.isInKioskAutoPrintMode_ = |
| 483 } | 490 event.initialSettings.isInKioskAutoPrintMode; |
| 484 | 491 this.destinationStore_.initialDestinationId = |
| 485 /** | 492 event.initialSettings.initialDestinationId; |
| 486 * Checks if |previewResponseId| matches |lastPreviewRequestId|. Used to ignore | 493 this.printTicketStore_.initialize( |
| 487 * obsolete preview data responses. | 494 event.initialSettings.isDocumentModifiable, |
| 488 * @param {number} previewResponseId The id to check. | 495 event.initialSettings.isDuplexEnabled, |
| 489 * @return {boolean} True if previewResponseId reffers to the expected response. | 496 event.initialSettings.isHeaderFooterEnabled, |
| 490 */ | 497 event.initialSettings.marginsType, |
| 491 function isExpectedPreviewResponse(previewResponseId) { | 498 event.initialSettings.customMargins, |
| 492 return lastPreviewRequestID == previewResponseId; | 499 event.initialSettings.thousandsDelimeter, |
| 493 } | 500 event.initialSettings.decimalDelimeter, |
| 494 | 501 event.initialSettings.unitType); |
| 495 /** | 502 |
| 496 * Returns the name of the selected printer or the empty string if no | 503 this.nativeLayer_.startGetLocalDestinations(); |
| 497 * printer is selected. | 504 }, |
| 498 * @return {string} The name of the currently selected printer. | 505 |
| 499 */ | 506 /** |
| 500 function getSelectedPrinterName() { | 507 * Calls when the native layer enables Google Cloud Print integration. |
| 501 var printerList = $('printer-list'); | 508 * Fetches the user's cloud printers. |
| 502 var selectedPrinter = printerList.selectedIndex; | 509 * @param {cr.Event} event Contains the base URL of the Google Cloud Print |
| 503 if (selectedPrinter < 0) | 510 * service. |
| 504 return ''; | 511 * @private |
| 505 return printerList.options[selectedPrinter].value; | 512 */ |
| 506 } | 513 onCloudPrintEnable_: function(event) { |
| 507 | 514 this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface( |
| 508 /** | 515 event.baseCloudPrintUrl); |
| 509 * Asks the browser to print the preview PDF based on current print | 516 this.tracker.add( |
| 510 * settings. If the preview is still loading, printPendingFile() will get | 517 this.cloudPrintInterface_, |
| 511 * called once the preview loads. | 518 cloudprint.CloudPrintInterface.EventType.SEARCH_DONE, |
| 512 */ | 519 this.onCloudPrintSearchDone_.bind(this)); |
| 513 function requestToPrintDocument() { | 520 this.tracker.add( |
| 514 hasPendingPrintDocumentRequest = !isPrintReadyMetafileReady; | 521 this.cloudPrintInterface_, |
| 515 var selectedPrinterName = getSelectedPrinterName(); | 522 cloudprint.CloudPrintInterface.EventType.PRINTER_DONE, |
| 516 var printToPDF = selectedPrinterName == PRINT_TO_PDF; | 523 this.onCloudPrintPrinterDone_.bind(this)); |
| 517 var printWithCloudPrint = selectedPrinterName == PRINT_WITH_CLOUD_PRINT; | 524 this.tracker.add( |
| 518 if (hasPendingPrintDocumentRequest) { | 525 this.cloudPrintInterface_, |
| 519 if (previewAppRequested) { | 526 cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE, |
| 520 previewArea.showCustomMessage( | 527 this.onCloudPrintSubmitDone_.bind(this)); |
| 528 this.tracker.add( |
| 529 this.cloudPrintInterface_, |
| 530 cloudprint.CloudPrintInterface.EventType.ERROR, |
| 531 this.onCloudPrintError_.bind(this)); |
| 532 |
| 533 var printWithCloudPrintDest = |
| 534 this.createPrintWithCloudPrintDestination_(); |
| 535 this.destinationStore_.insertDestination(printWithCloudPrintDest); |
| 536 |
| 537 if (cr.isChromeOS) { |
| 538 this.cloudPrintInterface_.search(true /*isRecent*/); |
| 539 this.fetchState_ |= PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS; |
| 540 } |
| 541 }, |
| 542 |
| 543 /** |
| 544 * Called when the native layer gets local destinations. Adds local |
| 545 * destination objects received from the operating system to the destination |
| 546 * store. Also adds a print-to-pdf printer. |
| 547 * @param {cr.Event} Contains the local destinations to set. |
| 548 * @private |
| 549 */ |
| 550 onLocalDestinationsSet_: function(event) { |
| 551 var localDestinations = []; |
| 552 for (var destInfo, i = 0; destInfo = event.destinationInfos[i]; i++) { |
| 553 localDestinations.push( |
| 554 print_preview.LocalDestinationParser.parse(destInfo)); |
| 555 } |
| 556 localDestinations.push(this.createLocalPdfPrintDestination_()); |
| 557 this.destinationStore_.insertDestinations(localDestinations); |
| 558 this.fetchState_ &= ~PrintPreview.FetchState_.LOCAL_DESTINATIONS; |
| 559 }, |
| 560 |
| 561 /** |
| 562 * Called when the native layer retrieves the capabilities for the selected |
| 563 * local destination. |
| 564 * @param {cr.Event} event Contains the capabilities of the local print |
| 565 * destination. |
| 566 * @private |
| 567 */ |
| 568 onLocalDestinationCapabilitiesSet_: function(event) { |
| 569 // TODO There may be a race condition here. This method is assumed to |
| 570 // return capabilities for the currently selected printer. But between the |
| 571 // time the local printer was selected and the capabilities were |
| 572 // retrieved, the selected printer can change. One way to address this is |
| 573 // to include the destination ID in the settingsInfo parameter. |
| 574 var selectedDestination = this.destinationStore_.selectedDestination; |
| 575 if (selectedDestination.isLocal) { |
| 576 var capabilities = print_preview.LocalCapabilitiesParser.parse( |
| 577 event.settingsInfo); |
| 578 selectedDestination.capabilities = capabilities; |
| 579 this.printTicketStore_.updateDestinationCapabilities(capabilities); |
| 580 this.printIfReady_(); |
| 581 } |
| 582 }, |
| 583 |
| 584 /** |
| 585 * Called from native layer after the user was requested to sign in, and did |
| 586 * so successfully. |
| 587 * @private |
| 588 */ |
| 589 onDestinationsReload_: function() { |
| 590 this.destinationStore_.clear(); |
| 591 this.nativeLayer_.startGetLocalDestinations(); |
| 592 if (this.cloudPrintInterface_) { |
| 593 // Fetch recent printers. |
| 594 this.cloudPrintInterface_.search(true /*isRecent*/); |
| 595 // Fetch the full printer list. |
| 596 this.cloudPrintInterface_.search(false /*isRecent*/); |
| 597 } |
| 598 this.fetchState_ = |
| 599 PrintPreview.FetchState_.LOCAL_DESTINATIONS | |
| 600 PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS | |
| 601 PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS; |
| 602 }, |
| 603 |
| 604 /** |
| 605 * Called from the native layer when ready to print to Google Cloud Print. |
| 606 * @param {cr.Event} event Contains the body to send in the HTTP request. |
| 607 * @private |
| 608 */ |
| 609 onPrintToCloud_: function(event) { |
| 610 if (this.uiState_ != PrintPreview.UiState_.PRINTING) { |
| 611 throw Error( |
| 612 'Document ready to be sent to the cloud when not in printing ' + |
| 613 'state: ' + this.uiState_); |
| 614 } |
| 615 if (this.cloudPrintInterface_) { |
| 616 this.cloudPrintInterface_.submit(event.data); |
| 617 } else { |
| 618 throw Error('Google Cloud Print is not enabled'); |
| 619 } |
| 620 }, |
| 621 |
| 622 /** |
| 623 * Called from the native layer when the user cancels the save-to-pdf file |
| 624 * selection dialog. |
| 625 * @private |
| 626 */ |
| 627 onFileSelectionCancel_: function() { |
| 628 if (this.uiState_ != PrintPreview.UiState_.FILE_SELECTION) { |
| 629 throw Error( |
| 630 'File selection cancelled when not in file-selection state: ' + |
| 631 this.uiState_); |
| 632 } |
| 633 // TODO Reenable controls. |
| 634 this.uiState_ = PrintPreview.UiState_.READY; |
| 635 }, |
| 636 |
| 637 /** |
| 638 * Called from the native layer when save-to-pdf file selection is complete. |
| 639 * @private |
| 640 */ |
| 641 onFileSelectionComplete_: function() { |
| 642 if (this.uiState_ != PrintPreview.UiState_.FILE_SELECTION) { |
| 643 throw Error( |
| 644 'File selection completed when not in file-selection state: ' + |
| 645 this.uiState_); |
| 646 } |
| 647 this.disable_(); |
| 648 this.previewArea_.showCustomMessage( |
| 649 localStrings.getString('printingToPDFInProgress')); |
| 650 // TODO |
| 651 }, |
| 652 |
| 653 /** |
| 654 * Called when the Google Cloud Print search API call completes. Adds |
| 655 * destinations to the printer store and selects one if it matches the |
| 656 * initial destination. |
| 657 * @param {cr.Event} event Contains the new cloud destinations. |
| 658 * @private |
| 659 */ |
| 660 onCloudPrintSearchDone_: function(event) { |
| 661 this.destinationStore_.insertDestinations(event.printers); |
| 662 if (event.isRecent) { |
| 663 this.fetchState_ &= ~PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS; |
| 664 } else { |
| 665 this.fetchState_ &= ~PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS; |
| 666 } |
| 667 }, |
| 668 |
| 669 /** |
| 670 * Called when the Google Cloud Print printer API call completes. Updates |
| 671 * the UI with the newly received capabilities. |
| 672 * @param {cr.Event} event Contains the destination returned in the printer |
| 673 * API call. |
| 674 */ |
| 675 onCloudPrintPrinterDone_: function(event) { |
| 676 var dest = this.destinationStore_.updateDestination(event.printer); |
| 677 if (this.destinationStore_.selectedDestination == dest) { |
| 678 this.printTicketStore_.updateDestinationCapabilities(dest.capabilities); |
| 679 this.printIfReady_(); |
| 680 } |
| 681 }, |
| 682 |
| 683 onCloudPrintSubmitDone_: function(event) { |
| 684 if (this.uiState_ != PrintPreview.UiState_.PRINTING) { |
| 685 throw Error( |
| 686 'Submited job to Google Cloud Print but not in printing state ' + |
| 687 this.uiState_); |
| 688 } |
| 689 this.close_(); |
| 690 }, |
| 691 |
| 692 /** |
| 693 * Called when there was an error communicating with Google Cloud print. |
| 694 * Displays an error message in the print header. |
| 695 * @param {cr.Event} event Contains the error message. |
| 696 * @private |
| 697 */ |
| 698 onCloudPrintError_: function(event) { |
| 699 if (cr.isChromeOS && event.message == '403') { |
| 700 this.nativeLayer_.startCloudPrintSignIn(); |
| 701 } else { |
| 702 this.printHeader_.setErrorMessage(event.message); |
| 703 } |
| 704 this.fetchState_ &= |
| 705 ~PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS & |
| 706 ~PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS; |
| 707 }, |
| 708 |
| 709 /** |
| 710 * Called when a new destination has been selected. Fetches the |
| 711 * destination's capability list. |
| 712 * @private |
| 713 */ |
| 714 onDestinationSelect_: function() { |
| 715 var destination = this.destinationStore_.selectedDestination; |
| 716 |
| 717 if (cr.isChromeOS && destination.isPrintWithCloudPrint) { |
| 718 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/); |
| 719 return; |
| 720 } |
| 721 |
| 722 // Fetch destination capabilities if necessary. |
| 723 if (!destination.capabilities) { |
| 724 if (destination.isLocal) { |
| 725 this.nativeLayer_.startGetLocalDestinationCapabilities( |
| 726 destination.id); |
| 727 } else if (this.cloudPrintInterface_) { |
| 728 this.cloudPrintInterface_.printer(destination.id); |
| 729 } else { |
| 730 // TODO Probably a cloud printer was initially selected, but cloud |
| 731 // print is no longer available. Maybe default to the system's local |
| 732 // default? What about Chrome OS? |
| 733 throw Error( |
| 734 'Selected destination is a cloud destination, but Google Cloud ' + |
| 735 'Print is not enabled'); |
| 736 } |
| 737 } else { |
| 738 this.printTicketStore_.updateDestinationCapabilities( |
| 739 destination.capabilities); |
| 740 } |
| 741 |
| 742 this.printIfReady_(); |
| 743 }, |
| 744 |
| 745 /** |
| 746 * Called when the preview area's preview generation is in progress. |
| 747 * @private |
| 748 */ |
| 749 onPreviewGenerationInProgress_: function() { |
| 750 this.isPreviewGenerationInProgress_ = true; |
| 751 }, |
| 752 |
| 753 /** |
| 754 * Called when the preview area's preview generation is complete. |
| 755 * @private |
| 756 */ |
| 757 onPreviewGenerationDone_: function() { |
| 758 this.isPreviewGenerationInProgress_ = false; |
| 759 this.printIfReady_(); |
| 760 }, |
| 761 |
| 762 /** |
| 763 * Called when the preview area's preview failed to load. |
| 764 * @private |
| 765 */ |
| 766 onPreviewGenerationFail_: function() { |
| 767 this.isPreviewGenerationInProgress_ = false; |
| 768 if (this.uiState_ == PrintPreview.UiState_.PRINTING) { |
| 769 this.nativeLayer_.startCancelPendingPrint(); |
| 770 } |
| 771 }, |
| 772 |
| 773 onSystemDialogLinkClicked_: function() { |
| 774 setIsVisible($('dialog-throbber'), true); |
| 775 this.openSystemPrintDialog_(); |
| 776 }, |
| 777 |
| 778 /** |
| 779 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf |
| 780 * preview app. |
| 781 * @private |
| 782 */ |
| 783 onOpenPdfInPreviewLinkClick_: function() { |
| 784 if (this.uiState_ != PrintPreview.UiState_.READY) { |
| 785 throw Error( |
| 786 'Trying to open pdf in preview when not in ready state: ' + |
| 787 this.uiState_); |
| 788 } |
| 789 setIsVisible($('open-preview-app-throbber'), true); |
| 790 this.disable_(); |
| 791 this.previewArea_.showCustomMessage( |
| 521 localStrings.getString('openingPDFInPreview')); | 792 localStrings.getString('openingPDFInPreview')); |
| 522 } else if (printToPDF) { | 793 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/); |
| 523 sendPrintDocumentRequest(); | 794 }, |
| 524 } else if (printWithCloudPrint) { | 795 |
| 525 previewArea.showCustomMessage( | 796 /** |
| 526 localStrings.getString('printWithCloudPrintWait')); | 797 * Called when the print header's print button is clicked. Prints the |
| 527 disableInputElementsInSidebar(); | 798 * document. |
| 528 } else { | 799 * @private |
| 529 isTabHidden = true; | 800 */ |
| 530 chrome.send('hidePreview'); | 801 onPrintButtonClick_: function() { |
| 802 if (this.uiState_ != PrintPreview.UiState_.READY) { |
| 803 throw Error( |
| 804 'Trying to print when not in ready state: ' + this.uiState_); |
| 805 } |
| 806 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/); |
| 807 }, |
| 808 |
| 809 /** |
| 810 * Called when the print header's cancel button is clicked. Closes the |
| 811 * print dialog. |
| 812 * @private |
| 813 */ |
| 814 onCancelButtonClick_: function() { |
| 815 this.close_(); |
| 816 }, |
| 817 |
| 818 /** |
| 819 * Consume escape key presses and ctrl + shift + p. Delegate everything else |
| 820 * to the preview area. |
| 821 * @param {KeyboardEvent} e The keyboard event. |
| 822 * @private |
| 823 */ |
| 824 onKeyDown_: function(e) { |
| 825 // Escape key closes the dialog. |
| 826 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey && |
| 827 !e.metaKey) { |
| 828 this.close_(); |
| 829 e.preventDefault(); |
| 830 return; |
| 831 } |
| 832 |
| 833 // Ctrl + Shift + p / Mac equivalent. |
| 834 if (e.keyCode == 80) { |
| 835 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) || |
| 836 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) { |
| 837 this.openSystemPrintDialog_(); |
| 838 e.preventDefault(); |
| 839 return; |
| 840 } |
| 841 } |
| 842 |
| 843 // Pass certain directional keyboard events to the PDF viewer. |
| 844 this.previewArea_.handleDirectionalKeyEvent(e); |
| 845 }, |
| 846 |
| 847 /** |
| 848 * Called when native layer receives invalid settings for a print request. |
| 849 * @private |
| 850 */ |
| 851 onSettingsInvalid_: function() { |
| 852 this.uiState_ = PrintPreview.UiState_.ERROR; |
| 853 this.previewArea_.showCustomMessage( |
| 854 localStrings.getString('invalidPrinterSettings')); |
| 531 } | 855 } |
| 532 return; | 856 }; |
| 533 } | 857 |
| 534 | 858 // Export |
| 535 if (printToPDF || previewAppRequested) { | 859 return { |
| 536 sendPrintDocumentRequest(); | 860 PrintPreview: PrintPreview |
| 537 } else { | 861 }; |
| 538 window.setTimeout(function() { sendPrintDocumentRequest(); }, 1000); | 862 }); |
| 539 } | 863 |
| 540 } | 864 // Pull in all other scripts in a single shot. |
| 541 | 865 <include src="data/page_number_set.js"/> |
| 542 /** | 866 <include src="data/destination.js"/> |
| 543 * Sends a message to cancel the pending print request. | 867 <include src="data/local_parsers.js"/> |
| 544 */ | 868 <include src="data/cloud_parsers.js"/> |
| 545 function cancelPendingPrintRequest() { | 869 <include src="data/chromium_capabilities.js"/> |
| 546 if (isTabHidden) | 870 <include src="data/cloud_capabilities.js"/> |
| 547 chrome.send('cancelPendingPrintRequest'); | 871 <include src="data/destination_store.js"/> |
| 548 } | 872 <include src="data/margins.js"/> |
| 549 | 873 <include src="data/document_info.js"/> |
| 550 /** | 874 <include src="data/printable_area.js"/> |
| 551 * Sends a message to initiate print workflow. | 875 <include src="data/measurement_system.js"/> |
| 552 */ | 876 <include src="data/print_ticket_store.js"/> |
| 553 function sendPrintDocumentRequest() { | 877 <include src="data/coordinate2d.js"/> |
| 554 var printerList = $('printer-list'); | 878 <include src="data/size.js"/> |
| 555 var printer = printerList[printerList.selectedIndex]; | 879 <include src="data/capabilities_holder.js"/> |
| 556 chrome.send('saveLastPrinter', [printer.value, cloudprint.getData(printer)]); | 880 |
| 557 | 881 <include src="data/ticket_items/ticket_item.js"/> |
| 558 var settings = getSettings(); | 882 |
| 559 if (cr.isMac && previewAppRequested) | 883 <include src="data/ticket_items/custom_margins.js"/> |
| 560 settings.OpenPDFInPreview = true; | 884 <include src="data/ticket_items/collate.js"/> |
| 561 | 885 <include src="data/ticket_items/color.js"/> |
| 562 chrome.send('print', [JSON.stringify(settings), | 886 <include src="data/ticket_items/copies.js"/> |
| 563 cloudprint.getPrintTicketJSON(printer)]); | 887 <include src="data/ticket_items/duplex.js"/> |
| 564 } | 888 <include src="data/ticket_items/header_footer.js"/> |
| 565 | 889 <include src="data/ticket_items/landscape.js"/> |
| 566 /** | 890 <include src="data/ticket_items/margins_type.js"/> |
| 567 * Loads the selected preview pages. | 891 <include src="data/ticket_items/page_range.js"/> |
| 568 */ | 892 |
| 569 function loadSelectedPages() { | 893 <include src="native_layer.js"/> |
| 570 pageSettings.updatePageSelection(); | |
| 571 var pageSet = pageSettings.previouslySelectedPages; | |
| 572 var pageCount = pageSet.length; | |
| 573 if (pageCount == 0 || currentPreviewUid == '') | |
| 574 return; | |
| 575 | |
| 576 cr.dispatchSimpleEvent(document, customEvents.UPDATE_SUMMARY); | |
| 577 for (var i = 0; i < pageCount; i++) | |
| 578 onDidPreviewPage(pageSet[i] - 1, currentPreviewUid, lastPreviewRequestID); | |
| 579 } | |
| 580 | |
| 581 /** | |
| 582 * Asks the browser to generate a preview PDF based on current print settings. | |
| 583 */ | |
| 584 function requestPrintPreview() { | |
| 585 if (!isTabHidden) | |
| 586 previewArea.showLoadingAnimation(); | |
| 587 | |
| 588 if (!hasPendingPreviewRequest && previewModifiable && | |
| 589 hasOnlyPageSettingsChanged()) { | |
| 590 loadSelectedPages(); | |
| 591 generateDraftData = false; | |
| 592 } else { | |
| 593 hasPendingPreviewRequest = true; | |
| 594 generateDraftData = true; | |
| 595 pageSettings.updatePageSelection(); | |
| 596 } | |
| 597 | |
| 598 printSettings.save(); | |
| 599 layoutSettings.updateState(); | |
| 600 previewArea.resetState(); | |
| 601 isPrintReadyMetafileReady = false; | |
| 602 isFirstPageLoaded = false; | |
| 603 | |
| 604 var totalPageCount = pageSettings.totalPageCount; | |
| 605 if (!previewModifiable && totalPageCount > 0) | |
| 606 generateDraftData = false; | |
| 607 | |
| 608 var pageCount = totalPageCount != undefined ? totalPageCount : -1; | |
| 609 chrome.send('getPreview', [JSON.stringify(getSettingsWithRequestID()), | |
| 610 pageCount, | |
| 611 previewModifiable]); | |
| 612 } | |
| 613 | |
| 614 /** | |
| 615 * Called from PrintPreviewUI::OnFileSelectionCancelled to notify the print | |
| 616 * preview tab regarding the file selection cancel event. | |
| 617 */ | |
| 618 function fileSelectionCancelled() { | |
| 619 printHeader.enableCancelButton(); | |
| 620 } | |
| 621 | |
| 622 /** | |
| 623 * Called from PrintPreviewUI::OnFileSelectionCompleted to notify the print | |
| 624 * preview tab regarding the file selection completed event. | |
| 625 */ | |
| 626 function fileSelectionCompleted() { | |
| 627 // If the file selection is completed and the tab is not already closed it | |
| 628 // means that a pending print to pdf request exists. | |
| 629 disableInputElementsInSidebar(); | |
| 630 previewArea.showCustomMessage( | |
| 631 localStrings.getString('printingToPDFInProgress')); | |
| 632 } | |
| 633 | |
| 634 /** | |
| 635 * Set the default printer. If there is one, generate a print preview. | |
| 636 * @param {string} printerName Name of the default printer. Empty if none. | |
| 637 * @param {string} cloudPrintData Cloud print related data to restore if | |
| 638 * the default printer is a cloud printer. | |
| 639 */ | |
| 640 function setDefaultPrinter(printerName, cloudPrintData) { | |
| 641 // Add a placeholder value so the printer list looks valid. | |
| 642 addDestinationListOption('', '', true, true, true); | |
| 643 if (printerName) { | |
| 644 defaultOrLastUsedPrinterName = printerName; | |
| 645 if (cloudPrintData) { | |
| 646 cloudprint.setDefaultPrinter(printerName, | |
| 647 cloudPrintData, | |
| 648 addDestinationListOptionAtPosition, | |
| 649 doUpdateCloudPrinterCapabilities); | |
| 650 } else { | |
| 651 $('printer-list')[0].value = defaultOrLastUsedPrinterName; | |
| 652 updateControlsWithSelectedPrinterCapabilities(); | |
| 653 } | |
| 654 } | |
| 655 chrome.send('getPrinters'); | |
| 656 } | |
| 657 | |
| 658 /** | |
| 659 * Fill the printer list drop down. | |
| 660 * Called from PrintPreviewHandler::SetupPrinterList(). | |
| 661 * @param {Array} printers Array of printer info objects. | |
| 662 */ | |
| 663 function setPrinters(printers) { | |
| 664 var printerList = $('printer-list'); | |
| 665 // Remove empty entry added by setDefaultPrinter. | |
| 666 if (printerList[0] && printerList[0].textContent == '') | |
| 667 printerList.remove(0); | |
| 668 for (var i = 0; i < printers.length; ++i) { | |
| 669 var isDefault = (printers[i].deviceName == defaultOrLastUsedPrinterName); | |
| 670 addDestinationListOption(printers[i].printerName, printers[i].deviceName, | |
| 671 isDefault, false, false); | |
| 672 } | |
| 673 | |
| 674 if (printers.length != 0) | |
| 675 addDestinationListOption('', '', false, true, true); | |
| 676 | |
| 677 // Adding option for saving PDF to disk. | |
| 678 addDestinationListOption(localStrings.getString('printToPDF'), | |
| 679 PRINT_TO_PDF, | |
| 680 defaultOrLastUsedPrinterName == PRINT_TO_PDF, | |
| 681 false, | |
| 682 false); | |
| 683 addDestinationListOption('', '', false, true, true); | |
| 684 if (useCloudPrint) { | |
| 685 addDestinationListOption(localStrings.getString('printWithCloudPrint'), | |
| 686 PRINT_WITH_CLOUD_PRINT, | |
| 687 false, | |
| 688 false, | |
| 689 false); | |
| 690 addDestinationListOption('', '', false, true, true); | |
| 691 } | |
| 692 // Add options to manage printers. | |
| 693 if (!cr.isChromeOS) { | |
| 694 addDestinationListOption(localStrings.getString('managePrinters'), | |
| 695 MANAGE_LOCAL_PRINTERS, false, false, false); | |
| 696 } else if (useCloudPrint) { | |
| 697 // Fetch recent printers. | |
| 698 cloudprint.fetchPrinters(addDestinationListOptionAtPosition, false); | |
| 699 // Fetch the full printer list. | |
| 700 cloudprint.fetchPrinters(addDestinationListOptionAtPosition, true); | |
| 701 addDestinationListOption(localStrings.getString('managePrinters'), | |
| 702 MANAGE_CLOUD_PRINTERS, false, false, false); | |
| 703 } | |
| 704 | |
| 705 printerList.disabled = false; | |
| 706 | |
| 707 if (!hasRequestedPreview()) | |
| 708 updateControlsWithSelectedPrinterCapabilities(); | |
| 709 } | |
| 710 | |
| 711 /** | |
| 712 * Creates an option that can be added to the printer destination list. | |
| 713 * @param {string} optionText specifies the option text content. | |
| 714 * @param {string} optionValue specifies the option value. | |
| 715 * @param {boolean} isDefault is true if the option needs to be selected. | |
| 716 * @param {boolean} isDisabled is true if the option needs to be disabled. | |
| 717 * @param {boolean} isSeparator is true if the option is a visual separator and | |
| 718 * needs to be disabled. | |
| 719 * @return {Object} The created option. | |
| 720 */ | |
| 721 function createDestinationListOption(optionText, optionValue, isDefault, | |
| 722 isDisabled, isSeparator) { | |
| 723 var option = document.createElement('option'); | |
| 724 option.textContent = optionText; | |
| 725 option.value = optionValue; | |
| 726 option.selected = isDefault; | |
| 727 option.disabled = isSeparator || isDisabled; | |
| 728 // Adding attribute for improved accessibility. | |
| 729 if (isSeparator) | |
| 730 option.setAttribute('role', 'separator'); | |
| 731 return option; | |
| 732 } | |
| 733 | |
| 734 /** | |
| 735 * Adds an option to the printer destination list. | |
| 736 * @param {string} optionText specifies the option text content. | |
| 737 * @param {string} optionValue specifies the option value. | |
| 738 * @param {boolean} isDefault is true if the option needs to be selected. | |
| 739 * @param {boolean} isDisabled is true if the option needs to be disabled. | |
| 740 * @param {boolean} isSeparator is true if the option serves just as a | |
| 741 * separator. | |
| 742 * @return {Object} The created option. | |
| 743 */ | |
| 744 function addDestinationListOption(optionText, optionValue, isDefault, | |
| 745 isDisabled, isSeparator) { | |
| 746 var option = createDestinationListOption(optionText, | |
| 747 optionValue, | |
| 748 isDefault, | |
| 749 isDisabled, | |
| 750 isSeparator); | |
| 751 $('printer-list').add(option); | |
| 752 return option; | |
| 753 } | |
| 754 | |
| 755 /** | |
| 756 * Adds an option to the printer destination list at a specified position. | |
| 757 * @param {number} position The index in the printer-list wher the option | |
| 758 should be created. | |
| 759 * @param {string} optionText specifies the option text content. | |
| 760 * @param {string} optionValue specifies the option value. | |
| 761 * @param {boolean} isDefault is true if the option needs to be selected. | |
| 762 * @param {boolean} isDisabled is true if the option needs to be disabled. | |
| 763 * @param {boolean} isSeparator is true if the option is a visual separator and | |
| 764 * needs to be disabled. | |
| 765 * @return {Object} The created option. | |
| 766 */ | |
| 767 function addDestinationListOptionAtPosition(position, | |
| 768 optionText, | |
| 769 optionValue, | |
| 770 isDefault, | |
| 771 isDisabled, | |
| 772 isSeparator) { | |
| 773 var option = createDestinationListOption(optionText, | |
| 774 optionValue, | |
| 775 isDefault, | |
| 776 isDisabled, | |
| 777 isSeparator); | |
| 778 var printerList = $('printer-list'); | |
| 779 var before = printerList[position]; | |
| 780 printerList.add(option, before); | |
| 781 return option; | |
| 782 } | |
| 783 /** | |
| 784 * Sets the color mode for the PDF plugin. | |
| 785 * Called from PrintPreviewHandler::ProcessColorSetting(). | |
| 786 * @param {boolean} color is true if the PDF plugin should display in color. | |
| 787 */ | |
| 788 function setColor(color) { | |
| 789 if (!previewArea.pdfPlugin) | |
| 790 return; | |
| 791 | |
| 792 previewArea.pdfPlugin.grayscale(!color); | |
| 793 var printerList = $('printer-list'); | |
| 794 cloudprint.setColor(printerList[printerList.selectedIndex], color); | |
| 795 } | |
| 796 | |
| 797 /** | |
| 798 * Display an error message when print preview fails. | |
| 799 * Called from PrintPreviewMessageHandler::OnPrintPreviewFailed(). | |
| 800 */ | |
| 801 function printPreviewFailed() { | |
| 802 previewArea.displayErrorMessageAndNotify( | |
| 803 localStrings.getString('previewFailed')); | |
| 804 } | |
| 805 | |
| 806 /** | |
| 807 * Display an error message when encountered invalid printer settings. | |
| 808 * Called from PrintPreviewMessageHandler::OnInvalidPrinterSettings(). | |
| 809 */ | |
| 810 function invalidPrinterSettings() { | |
| 811 if (cr.isMac) { | |
| 812 if (previewAppRequested) { | |
| 813 $('open-preview-app-throbber').hidden = true; | |
| 814 previewArea.clearCustomMessageWithDots(); | |
| 815 previewAppRequested = false; | |
| 816 hasPendingPrintDocumentRequest = false; | |
| 817 enableInputElementsInSidebar(); | |
| 818 } | |
| 819 $('open-pdf-in-preview-link').disabled = true; | |
| 820 } | |
| 821 previewArea.displayErrorMessageAndNotify( | |
| 822 localStrings.getString('invalidPrinterSettings')); | |
| 823 } | |
| 824 | |
| 825 /** | |
| 826 * Called when the PDF plugin loads its document. | |
| 827 */ | |
| 828 function onPDFLoad() { | |
| 829 if (previewModifiable) { | |
| 830 setPluginPreviewPageCount(); | |
| 831 } | |
| 832 // Instruct the plugin which page numbers to display in the page number | |
| 833 // indicator. | |
| 834 previewArea.pdfPlugin.setPageNumbers( | |
| 835 JSON.stringify(pageSettings.selectedPagesSet)); | |
| 836 cr.dispatchSimpleEvent(document, customEvents.PDF_LOADED); | |
| 837 isFirstPageLoaded = true; | |
| 838 checkAndHideOverlayLayerIfValid(); | |
| 839 sendPrintDocumentRequestIfNeeded(); | |
| 840 if (printAutomaticallyInKioskMode) | |
| 841 printHeader.printButton.click(); | |
| 842 } | |
| 843 | |
| 844 function setPluginPreviewPageCount() { | |
| 845 previewArea.pdfPlugin.printPreviewPageCount( | |
| 846 pageSettings.previouslySelectedPages.length); | |
| 847 } | |
| 848 | |
| 849 /** | |
| 850 * Update the page count and check the page range. | |
| 851 * Called from PrintPreviewUI::OnDidGetPreviewPageCount(). | |
| 852 * @param {number} pageCount The number of pages. | |
| 853 * @param {number} previewResponseId The preview request id that resulted in | |
| 854 * this response. | |
| 855 */ | |
| 856 function onDidGetPreviewPageCount(pageCount, previewResponseId) { | |
| 857 if (!isExpectedPreviewResponse(previewResponseId)) | |
| 858 return; | |
| 859 pageSettings.updateState(pageCount); | |
| 860 if (!previewModifiable && pageSettings.requestPrintPreviewIfNeeded()) | |
| 861 return; | |
| 862 | |
| 863 cr.dispatchSimpleEvent(document, customEvents.UPDATE_SUMMARY); | |
| 864 } | |
| 865 | |
| 866 /** | |
| 867 * @param {{contentWidth: number, contentHeight: number, marginLeft: number, | |
| 868 * marginRight: number, marginTop: number, marginBottom: number, | |
| 869 * printableAreaX: number, printableAreaY: number, | |
| 870 * printableAreaWidth: number, printableAreaHeight: number}} pageLayout | |
| 871 * Specifies default page layout details in points. | |
| 872 * @param {boolean} hasCustomPageSizeStyle Indicates whether the previewed | |
| 873 * document has a custom page size style. | |
| 874 */ | |
| 875 function onDidGetDefaultPageLayout(pageLayout, hasCustomPageSizeStyle) { | |
| 876 hasPageSizeStyle = hasCustomPageSizeStyle; | |
| 877 marginSettings.currentDefaultPageLayout = new print_preview.PageLayout( | |
| 878 pageLayout.contentWidth, | |
| 879 pageLayout.contentHeight, | |
| 880 pageLayout.marginLeft, | |
| 881 pageLayout.marginTop, | |
| 882 pageLayout.marginRight, | |
| 883 pageLayout.marginBottom); | |
| 884 headerFooterSettings.checkAndHideHeaderFooterOption( | |
| 885 pageLayout, marginSettings.selectedMarginsValue); | |
| 886 } | |
| 887 | |
| 888 /** | |
| 889 * This function sends a request to hide the overlay layer only if there is no | |
| 890 * pending print document request and we are not waiting for the print ready | |
| 891 * metafile. | |
| 892 */ | |
| 893 function checkAndHideOverlayLayerIfValid() { | |
| 894 var selectedPrinter = getSelectedPrinterName(); | |
| 895 var printToDialog = selectedPrinter == PRINT_TO_PDF || | |
| 896 selectedPrinter == PRINT_WITH_CLOUD_PRINT; | |
| 897 if ((printToDialog || !previewModifiable) && | |
| 898 !isPrintReadyMetafileReady && hasPendingPrintDocumentRequest) { | |
| 899 return; | |
| 900 } | |
| 901 previewArea.hideOverlayLayer(); | |
| 902 } | |
| 903 | |
| 904 /** | |
| 905 * Called when no pipelining previewed pages. | |
| 906 * @param {string} previewUid Preview unique identifier. | |
| 907 * @param {number} previewResponseId The preview request id that resulted in | |
| 908 * this response. | |
| 909 */ | |
| 910 function reloadPreviewPages(previewUid, previewResponseId) { | |
| 911 if (!isExpectedPreviewResponse(previewResponseId)) | |
| 912 return; | |
| 913 | |
| 914 cr.dispatchSimpleEvent(document, customEvents.UPDATE_PRINT_BUTTON); | |
| 915 checkAndHideOverlayLayerIfValid(); | |
| 916 var pageSet = pageSettings.previouslySelectedPages; | |
| 917 for (var i = 0; i < pageSet.length; i++) { | |
| 918 previewArea.pdfPlugin.loadPreviewPage( | |
| 919 getPageSrcURL(previewUid, pageSet[i] - 1), i); | |
| 920 } | |
| 921 | |
| 922 hasPendingPreviewRequest = false; | |
| 923 isPrintReadyMetafileReady = true; | |
| 924 previewArea.pdfLoaded = true; | |
| 925 sendPrintDocumentRequestIfNeeded(); | |
| 926 } | |
| 927 | |
| 928 /** | |
| 929 * Notification that a print preview page has been rendered. | |
| 930 * Check if the settings have changed and request a regeneration if needed. | |
| 931 * Called from PrintPreviewUI::OnDidPreviewPage(). | |
| 932 * @param {number} pageNumber The page number, 0-based. | |
| 933 * @param {string} previewUid Preview unique identifier. | |
| 934 * @param {number} previewResponseId The preview request id that resulted in | |
| 935 * this response. | |
| 936 */ | |
| 937 function onDidPreviewPage(pageNumber, previewUid, previewResponseId) { | |
| 938 if (!isExpectedPreviewResponse(previewResponseId)) | |
| 939 return; | |
| 940 | |
| 941 // Refactor | |
| 942 if (!previewModifiable) | |
| 943 return; | |
| 944 | |
| 945 if (pageSettings.requestPrintPreviewIfNeeded()) | |
| 946 return; | |
| 947 | |
| 948 var pageIndex = pageSettings.previouslySelectedPages.indexOf(pageNumber + 1); | |
| 949 if (pageIndex == -1) | |
| 950 return; | |
| 951 | |
| 952 currentPreviewUid = previewUid; | |
| 953 if (pageIndex == 0) | |
| 954 previewArea.createOrReloadPDFPlugin(pageNumber); | |
| 955 | |
| 956 previewArea.pdfPlugin.loadPreviewPage( | |
| 957 getPageSrcURL(previewUid, pageNumber), pageIndex); | |
| 958 | |
| 959 if (pageIndex + 1 == pageSettings.previouslySelectedPages.length) { | |
| 960 hasPendingPreviewRequest = false; | |
| 961 if (pageIndex != 0) | |
| 962 sendPrintDocumentRequestIfNeeded(); | |
| 963 } | |
| 964 } | |
| 965 | |
| 966 /** | |
| 967 * Update the print preview when new preview data is available. | |
| 968 * Create the PDF plugin as needed. | |
| 969 * Called from PrintPreviewUI::PreviewDataIsAvailable(). | |
| 970 * @param {string} previewUid Preview unique identifier. | |
| 971 * @param {number} previewResponseId The preview request id that resulted in | |
| 972 * this response. | |
| 973 */ | |
| 974 function updatePrintPreview(previewUid, previewResponseId) { | |
| 975 if (!isExpectedPreviewResponse(previewResponseId)) | |
| 976 return; | |
| 977 isPrintReadyMetafileReady = true; | |
| 978 | |
| 979 if (!previewModifiable) { | |
| 980 // If the preview is not modifiable the plugin has not been created yet. | |
| 981 currentPreviewUid = previewUid; | |
| 982 hasPendingPreviewRequest = false; | |
| 983 previewArea.createOrReloadPDFPlugin(PRINT_READY_DATA_INDEX); | |
| 984 } | |
| 985 | |
| 986 cr.dispatchSimpleEvent(document, customEvents.UPDATE_PRINT_BUTTON); | |
| 987 if (previewModifiable) | |
| 988 sendPrintDocumentRequestIfNeeded(); | |
| 989 } | |
| 990 | |
| 991 /** | |
| 992 * Checks to see if the requested print data is available for printing and | |
| 993 * sends a print document request if needed. | |
| 994 */ | |
| 995 function sendPrintDocumentRequestIfNeeded() { | |
| 996 if (!hasPendingPrintDocumentRequest || !isFirstPageLoaded) | |
| 997 return; | |
| 998 | |
| 999 // If the selected printer is PRINT_TO_PDF or PRINT_WITH_CLOUD_PRINT or | |
| 1000 // the preview source is not modifiable, we need the print ready data for | |
| 1001 // printing. If the preview source is modifiable, we need to wait till all | |
| 1002 // the requested pages are loaded in the plugin for printing. | |
| 1003 var selectedPrinter = getSelectedPrinterName(); | |
| 1004 var printToDialog = selectedPrinter == PRINT_TO_PDF || | |
| 1005 selectedPrinter == PRINT_WITH_CLOUD_PRINT; | |
| 1006 if (((printToDialog || !previewModifiable) && !isPrintReadyMetafileReady) || | |
| 1007 (previewModifiable && hasPendingPreviewRequest)) { | |
| 1008 return; | |
| 1009 } | |
| 1010 | |
| 1011 hasPendingPrintDocumentRequest = false; | |
| 1012 | |
| 1013 if (!areSettingsValid()) { | |
| 1014 cancelPendingPrintRequest(); | |
| 1015 return; | |
| 1016 } | |
| 1017 sendPrintDocumentRequest(); | |
| 1018 } | |
| 1019 | |
| 1020 /** | |
| 1021 * Check if only page selection has been changed since the last preview request | |
| 1022 * and is valid. | |
| 1023 * @return {boolean} true if the new page selection is valid. | |
| 1024 */ | |
| 1025 function hasOnlyPageSettingsChanged() { | |
| 1026 var tempPrintSettings = new PrintSettings(); | |
| 1027 tempPrintSettings.save(); | |
| 1028 | |
| 1029 return !!(printSettings.deviceName == tempPrintSettings.deviceName && | |
| 1030 printSettings.isLandscape == tempPrintSettings.isLandscape && | |
| 1031 printSettings.hasHeaderFooter == | |
| 1032 tempPrintSettings.hasHeaderFooter && | |
| 1033 pageSettings.hasPageSelectionChangedAndIsValid()); | |
| 1034 } | |
| 1035 | |
| 1036 /** | |
| 1037 * Called either when there is a scroll event or when the plugin size changes. | |
| 1038 */ | |
| 1039 function onPreviewPositionChanged() { | |
| 1040 marginSettings.onPreviewPositionChanged(); | |
| 1041 } | |
| 1042 | |
| 1043 /** | |
| 1044 * @return {boolean} true if a compatible pdf plugin exists. | |
| 1045 */ | |
| 1046 function checkCompatiblePluginExists() { | |
| 1047 var dummyPlugin = $('dummy-viewer'); | |
| 1048 var pluginInterface = [dummyPlugin.onload, | |
| 1049 dummyPlugin.goToPage, | |
| 1050 dummyPlugin.removePrintButton, | |
| 1051 dummyPlugin.loadPreviewPage, | |
| 1052 dummyPlugin.printPreviewPageCount, | |
| 1053 dummyPlugin.resetPrintPreviewUrl, | |
| 1054 dummyPlugin.onPluginSizeChanged, | |
| 1055 dummyPlugin.onScroll, | |
| 1056 dummyPlugin.pageXOffset, | |
| 1057 dummyPlugin.pageYOffset, | |
| 1058 dummyPlugin.setZoomLevel, | |
| 1059 dummyPlugin.setPageNumbers, | |
| 1060 dummyPlugin.setPageXOffset, | |
| 1061 dummyPlugin.setPageYOffset, | |
| 1062 dummyPlugin.getHorizontalScrollbarThickness, | |
| 1063 dummyPlugin.getVerticalScrollbarThickness, | |
| 1064 dummyPlugin.getPageLocationNormalized, | |
| 1065 dummyPlugin.getHeight, | |
| 1066 dummyPlugin.getWidth]; | |
| 1067 | |
| 1068 for (var i = 0; i < pluginInterface.length; i++) { | |
| 1069 if (!pluginInterface[i]) | |
| 1070 return false; | |
| 1071 } | |
| 1072 return true; | |
| 1073 } | |
| 1074 | |
| 1075 /** | |
| 1076 * Sets the default values and sends a request to regenerate preview data. | |
| 1077 * Resets the margin options only if |resetMargins| is true. | |
| 1078 * @param {boolean} resetMargins True if margin settings should be resetted. | |
| 1079 */ | |
| 1080 function setDefaultValuesAndRegeneratePreview(resetMargins) { | |
| 1081 if (resetMargins) | |
| 1082 marginSettings.resetMarginsIfNeeded(); | |
| 1083 pageSettings.resetState(); | |
| 1084 requestPrintPreview(); | |
| 1085 } | |
| 1086 | |
| 1087 /** | |
| 1088 * Class that represents the state of the print settings. | |
| 1089 * @constructor | |
| 1090 */ | |
| 1091 function PrintSettings() { | |
| 1092 this.deviceName = ''; | |
| 1093 this.isLandscape = ''; | |
| 1094 this.hasHeaderFooter = ''; | |
| 1095 } | |
| 1096 | |
| 1097 /** | |
| 1098 * Takes a snapshot of the print settings. | |
| 1099 */ | |
| 1100 PrintSettings.prototype.save = function() { | |
| 1101 this.deviceName = getSelectedPrinterName(); | |
| 1102 this.isLandscape = layoutSettings.isLandscape(); | |
| 1103 this.hasHeaderFooter = headerFooterSettings.hasHeaderFooter(); | |
| 1104 }; | |
| 1105 | |
| 1106 /** | |
| 1107 * Updates the title of the print preview tab according to |initiatorTabTitle|. | |
| 1108 * @param {string} initiatorTabTitle The title of the initiator tab. | |
| 1109 */ | |
| 1110 function setInitiatorTabTitle(initiatorTabTitle) { | |
| 1111 if (initiatorTabTitle == '') | |
| 1112 return; | |
| 1113 document.title = localStrings.getStringF( | |
| 1114 'printPreviewTitleFormat', initiatorTabTitle); | |
| 1115 } | |
| 1116 | |
| 1117 /** | |
| 1118 * Closes this print preview tab. | |
| 1119 */ | |
| 1120 function closePrintPreviewTab() { | |
| 1121 window.removeEventListener('keydown', onKeyDown); | |
| 1122 chrome.send('closePrintPreviewTab'); | |
| 1123 chrome.send('DialogClose'); | |
| 1124 } | |
| 1125 | |
| 1126 /** | |
| 1127 * Pass certain directional keyboard events to the PDF viewer. | |
| 1128 * @param {Event} e The keydown event. | |
| 1129 */ | |
| 1130 function tryToHandleDirectionKeyDown(e) { | |
| 1131 // Make sure the PDF plugin is there. | |
| 1132 if (!previewArea.pdfPlugin) | |
| 1133 return; | |
| 1134 | |
| 1135 // We only care about: PageUp, PageDown, Left, Up, Right, Down. | |
| 1136 if (!(e.keyCode == 33 || e.keyCode == 34 || | |
| 1137 (e.keyCode >= 37 && e.keyCode <= 40))) { | |
| 1138 return; | |
| 1139 } | |
| 1140 | |
| 1141 // If the user is holding a modifier key, ignore. | |
| 1142 if (e.metaKey || e.altKey || e.shiftKey || e.ctrlKey) | |
| 1143 return; | |
| 1144 | |
| 1145 // Don't handle the key event for these elements. | |
| 1146 var tagName = document.activeElement.tagName; | |
| 1147 if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'EMBED') | |
| 1148 return; | |
| 1149 | |
| 1150 // For the most part, if any div of header was the last clicked element, | |
| 1151 // then the active element is the body. Starting with the last clicked | |
| 1152 // element, and work up the DOM tree to see if any element has a scrollbar. | |
| 1153 // If there exists a scrollbar, do not handle the key event here. | |
| 1154 var element = document.activeElement; | |
| 1155 if (element == document.body) { | |
| 1156 if (lastClickedElement) | |
| 1157 element = lastClickedElement; | |
| 1158 while (element) { | |
| 1159 if (element.scrollHeight > element.clientHeight) | |
| 1160 return; | |
| 1161 element = element.parentElement; | |
| 1162 } | |
| 1163 } | |
| 1164 | |
| 1165 // No scroll bar anywhere, or the active element is something else, like a | |
| 1166 // button. Note: buttons have a bigger scrollHeight than clientHeight. | |
| 1167 previewArea.pdfPlugin.sendKeyEvent(e.keyCode); | |
| 1168 e.preventDefault(); | |
| 1169 } | |
| 1170 | |
| 1171 /** | |
| 1172 * Handle keyboard events. | |
| 1173 * @param {KeyboardEvent} e The keyboard event. | |
| 1174 */ | |
| 1175 function onKeyDown(e) { | |
| 1176 // Escape key closes the dialog. | |
| 1177 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) { | |
| 1178 printHeader.disableCancelButton(); | |
| 1179 closePrintPreviewTab(); | |
| 1180 e.preventDefault(); | |
| 1181 } | |
| 1182 // Ctrl + Shift + p / Mac equivalent. | |
| 1183 if (e.keyCode == 80) { | |
| 1184 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) || | |
| 1185 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) { | |
| 1186 window.removeEventListener('keydown', onKeyDown); | |
| 1187 onSystemDialogLinkClicked(); | |
| 1188 e.preventDefault(); | |
| 1189 } | |
| 1190 } | |
| 1191 | |
| 1192 tryToHandleDirectionKeyDown(e); | |
| 1193 } | |
| 1194 | |
| 1195 window.addEventListener('DOMContentLoaded', onLoad); | |
| 1196 window.addEventListener('keydown', onKeyDown); | |
| 1197 | |
| 1198 /// Pull in all other scripts in a single shot. | |
| 1199 <include src="print_preview_animations.js"/> | 894 <include src="print_preview_animations.js"/> |
| 1200 <include src="print_preview_cloud.js"/> | 895 <include src="cloud_print_interface.js"/> |
| 1201 <include src="print_preview_utils.js"/> | 896 <include src="print_preview_utils.js"/> |
| 1202 <include src="print_header.js"/> | 897 <include src="print_header.js"/> |
| 1203 <include src="page_settings.js"/> | 898 |
| 1204 <include src="copies_settings.js"/> | 899 <include src="settings/page_settings.js"/> |
| 1205 <include src="header_footer_settings.js"/> | 900 <include src="settings/copies_settings.js"/> |
| 1206 <include src="layout_settings.js"/> | 901 <include src="settings/header_footer_settings.js"/> |
| 1207 <include src="color_settings.js"/> | 902 <include src="settings/layout_settings.js"/> |
| 1208 <include src="margin_settings.js"/> | 903 <include src="settings/color_settings.js"/> |
| 1209 <include src="margin_textbox.js"/> | 904 <include src="settings/margin_settings.js"/> |
| 1210 <include src="margin_utils.js"/> | 905 <include src="settings/destination_settings.js"/> |
| 1211 <include src="margins_ui.js"/> | 906 |
| 1212 <include src="margins_ui_pair.js"/> | 907 <include src="previewarea/margin_control.js"/> |
| 1213 <include src="preview_area.js"/> | 908 <include src="previewarea/margin_control_container.js"/> |
| 909 <include src="previewarea/preview_area.js"/> |
| 910 <include src="preview_generator.js"/> |
| 911 |
| 912 var printPreview = new print_preview.PrintPreview(); |
| OLD | NEW |