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