Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: chrome/browser/resources/print_preview/print_preview.js

Issue 10108001: Refactor print preview web ui (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Resolve conflicts Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698