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

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: Fix fit-to-page tests 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 Might be a problem where might be in fetching destinations state, then
kmadhusu 2012/05/18 20:13:46 TODO(rltoscano):
6 // to file selection state, then cancel, which results in the fetching
7 // destinations state being lost.
8
9 // TODO Move data/* into print_preview.data namespace
kmadhusu 2012/05/18 20:13:46 TODO(rltoscano): Comment...
10
11 // TODO Handle case where cloud print is initial destination, but cloud print is
kmadhusu 2012/05/18 20:13:46 same here.
12 // not enabled.
6 13
7 var localStrings = new LocalStrings(); 14 var localStrings = new LocalStrings();
8 15
9 // If useCloudPrint is true we attempt to connect to cloud print 16 <include src="component.js"/>
10 // and populate the list of printers with cloud print printers. 17
11 var useCloudPrint = false; 18 cr.define('print_preview', function() {
12 19 'use strict';
13 // Store the last selected printer index. 20
14 var lastSelectedPrinterIndex = 0; 21 /**
15 22 * Container class for Chromium's print preview.
16 // Used to disable some printing options when the preview is not modifiable. 23 * @constructor
17 var previewModifiable = false; 24 * @extends {print_preview.Component}
18 25 */
19 // Used to identify whether the printing frame has specific page size style. 26 function PrintPreview() {
20 var hasPageSizeStyle = false; 27 print_preview.Component.call(this);
21 28
22 // Destination list special value constants. 29 /**
23 30 * Used to communicate with Chromium's print system.
24 /** @const */ var MANAGE_CLOUD_PRINTERS = 'manageCloudPrinters'; 31 * @type {!print_preview.NativeLayer}
25 /** @const */ var MANAGE_LOCAL_PRINTERS = 'manageLocalPrinters'; 32 * @private
26 /** @const */ var SIGN_IN = 'signIn'; 33 */
27 /** @const */ var PRINT_TO_PDF = 'Save as PDF'; 34 this.nativeLayer_ = new print_preview.NativeLayer();
28 /** @const */ var PRINT_WITH_CLOUD_PRINT = 'printWithCloudPrint'; 35
29 36 /**
30 // State of the print preview settings. 37 * Data store which holds print destinations.
31 var printSettings = new PrintSettings(); 38 * @type {!print_preview.DestinationStore}
32 39 * @private
33 // Print ready data index. 40 */
34 /** @const */ var PRINT_READY_DATA_INDEX = -1; 41 this.destinationStore_ = new print_preview.DestinationStore();
35 42
36 // The name of the default or last used printer. 43 /**
37 var defaultOrLastUsedPrinterName = ''; 44 * Storage of the print ticket used to create the print job.
38 45 * @type {!print_preview.PrintTicketStore}
39 // True when a pending print preview request exists. 46 * @private
40 var hasPendingPreviewRequest = false; 47 */
41 48 this.printTicketStore_ = new print_preview.PrintTicketStore(
42 // True when the first page is loaded in the plugin. 49 this.destinationStore_);
43 var isFirstPageLoaded = false; 50
44 51 /**
45 // The ID of the last preview request. 52 * Holds the print and cancel buttons and renders some document statistics.
46 var lastPreviewRequestID = -1; 53 * @type {!print_preview.PrintHeader}
47 54 * @private
48 // The ID of the initial preview request. 55 */
49 var initialPreviewRequestID = -1; 56 this.printHeader_ = new print_preview.PrintHeader(
50 57 this.printTicketStore_, this.destinationStore_);
51 // True when a pending print file request exists. 58 this.addChild(this.printHeader_);
52 var hasPendingPrintDocumentRequest = false; 59
53 60 /**
54 // True when the complete metafile for the previewed doc is ready. 61 * Component that renders the print destination.
55 var isPrintReadyMetafileReady = false; 62 * @type {!print_preview.DestinationSettings}
56 63 * @private
57 // True when preview tab is hidden. 64 */
58 var isTabHidden = false; 65 this.destinationSettings_ = new print_preview.DestinationSettings(
59 66 this.destinationStore_);
60 // True in kiosk mode where print preview can print automatically without 67 this.addChild(this.destinationSettings_);
61 // user intervention. See http://crbug.com/31395. 68
62 var printAutomaticallyInKioskMode = false; 69 /**
63 70 * Component that renders UI for entering in page range.
64 // @type {print_preview.PrintHeader} Holds the print and cancel buttons. 71 * @type {!print_preview.PageSettings}
65 var printHeader; 72 * @private
66 73 */
67 // @type {print_preview.PageSettings} Holds all the pages related settings. 74 this.pageSettings_ = new print_preview.PageSettings(this.printTicketStore_);
68 var pageSettings; 75 this.addChild(this.pageSettings_);
69 76
70 // @type {print_preview.CopiesSettings} Holds all the copies related settings. 77 /**
71 var copiesSettings; 78 * Component that renders the copies settings.
72 79 * @type {!print_preview.CopiesSettings}
73 // @type {print_preview.LayoutSettings} Holds all the layout related settings. 80 * @private
74 var layoutSettings; 81 */
75 82 this.copiesSettings_ = new print_preview.CopiesSettings(
76 // @type {print_preview.MarginSettings} Holds all the margin related settings. 83 this.printTicketStore_);
77 var marginSettings; 84 this.addChild(this.copiesSettings_);
78 85
79 // @type {print_preview.HeaderFooterSettings} Holds all the header footer 86 /**
80 // related settings. 87 * Component that renders the layout settings.
81 var headerFooterSettings; 88 * @type {!print_preview.LayoutSettings}
82 89 * @private
83 // @type {print_preview.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.onSystemDialogLinkClicked_.bind(this));
262 chrome.send('showSystemDialog'); 269 this.tracker.add(
263 } 270 $('cloud-print-dialog-link'),
264 271 'click',
265 /** 272 this.onSystemDialogLinkClicked_.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(window, 'keydown', this.onKeyDown_.bind(this));
303 /** 310 },
304 * Gets the selected printer capabilities and updates the controls accordingly. 311
305 */ 312 /**
306 function updateControlsWithSelectedPrinterCapabilities() { 313 * Sets whether the controls in the print preview are enabled.
307 var printerList = $('printer-list'); 314 * @param {boolean} isEnabled Whether the controls in the print preview are
308 var selectedIndex = printerList.selectedIndex; 315 * enabled.
309 if (selectedIndex < 0) 316 * @private
310 return; 317 */
311 if (cr.isMac) 318 setIsEnabled_: function(isEnabled) {
312 $('open-pdf-in-preview-link').disabled = false; 319 $('system-dialog-link').disabled = !isEnabled;
313 320 $('cloud-print-dialog-link').disabled = !isEnabled;
314 var skip_refresh = false; 321 $('open-pdf-in-preview-link').disabled = !isEnabled;
315 var selectedPrinterChanged = true; 322 this.printHeader_.isEnabled = isEnabled;
316 var selectedValue = printerList.options[selectedIndex].value; 323 this.destinationSettings_.isEnabled = isEnabled;
317 if (cloudprint.isCloudPrint(printerList.options[selectedIndex])) { 324 this.pageSettings_.isEnabled = isEnabled;
318 cloudprint.updatePrinterCaps(printerList.options[selectedIndex], 325 this.copiesSettings_.isEnabled = isEnabled;
319 doUpdateCloudPrinterCapabilities); 326 this.layoutSettings_.isEnabled = isEnabled;
320 skip_refresh = true; 327 this.colorSettings_.isEnabled = isEnabled;
321 } else if (selectedValue == SIGN_IN || 328 this.marginSettings_.isEnabled = isEnabled;
322 selectedValue == MANAGE_CLOUD_PRINTERS || 329 this.otherOptionsSettings_.isEnabled = isEnabled;
323 selectedValue == MANAGE_LOCAL_PRINTERS) { 330 },
324 printerList.selectedIndex = lastSelectedPrinterIndex; 331
325 chrome.send(selectedValue); 332 /**
326 skip_refresh = true; 333 * Creates a local PDF print destination.
327 selectedPrinterChanged = false; 334 * @return {!print_preview.Destination} Created print destination.
328 } else if (selectedValue == PRINT_TO_PDF || 335 * @private
329 selectedValue == PRINT_WITH_CLOUD_PRINT) { 336 */
330 updateWithPrinterCapabilities({ 337 createLocalPdfPrintDestination_: function() {
331 'disableColorOption': true, 338 var dest = new print_preview.Destination(
332 'setColorAsDefault': true, 339 print_preview.Destination.GooglePromotedId.LOCAL_PDF,
333 'setDuplexAsDefault': false, 340 localStrings.getString('printToPDF'),
334 'printerColorModelForColor': print_preview.ColorSettings.COLOR, 341 false /*isRecent*/,
335 'printerDefaultDuplexValue': copiesSettings.UNKNOWN_DUPLEX_MODE, 342 true /*isLocal*/);
336 'disableCopiesOption': true}); 343 dest.capabilities = new print_preview.ChromiumCapabilities(
337 if (cr.isChromeOS && selectedValue == PRINT_WITH_CLOUD_PRINT) 344 false /*hasCopiesCapability*/,
338 requestToPrintDocument(); 345 '1' /*defaultCopiesStr*/,
339 } else { 346 false /*hasCollateCapability*/,
340 // This message will call back to 'updateWithPrinterCapabilities' 347 false /*defaultIsCollateEnabled*/,
341 // function. 348 false /*hasDuplexCapability*/,
342 chrome.send('getPrinterCapabilities', [selectedValue]); 349 false /*defaultIsDuplexEnabled*/,
343 } 350 true /*hasOrientationCapability*/,
344 if (selectedPrinterChanged) 351 false /*defaultIsLandscapeEnabled*/,
345 dispatchPrinterSelectionChangedEvent(); 352 true /*hasColorCapability*/,
346 353 true /*defaultIsColorEnabled*/);
347 if (!skip_refresh) { 354 return dest;
348 lastSelectedPrinterIndex = selectedIndex; 355 },
349 356
350 // Regenerate the preview data based on selected printer settings. 357 /**
351 // Do not reset the margins if no preview request has been made. 358 * Creates a new "Print with Cloud Print" print destination. NOTE: this
352 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 359 * destination will appear as "Search for additional printers..." on
353 setDefaultValuesAndRegeneratePreview(resetMargins); 360 * Chrome OS.
354 } 361 * @return {!print_preview.Destination} Created print destination.
355 } 362 * @private
356 363 */
357 /** 364 createPrintWithCloudPrintDestination_: function() {
358 * Helper function to do the actual work of updating cloud printer 365 var dest = new print_preview.Destination(
359 * capabilities. 366 print_preview.Destination.GooglePromotedId.PRINT_WITH_CLOUD_PRINT,
360 * @param {Object} printer The printer object to set capabilities for. 367 localStrings.getString('printWithCloudPrint'),
361 */ 368 false /*isRecent*/,
362 function doUpdateCloudPrinterCapabilities(printer) { 369 false /*isLocal*/);
363 var settings = {'disableColorOption': !cloudprint.supportsColor(printer), 370 dest.capabilities = new print_preview.ChromiumCapabilities(
364 'setColorAsDefault': cloudprint.colorIsDefault(printer), 371 false /*hasCopiesCapability*/,
365 'disableCopiesOption': true, 372 '1' /*defaultCopiesStr*/,
366 'disableLandscapeOption': true}; 373 false /*hasCollateCapability*/,
367 updateWithPrinterCapabilities(settings); 374 false /*defaultIsCollateEnabled*/,
368 var printerList = $('printer-list'); 375 false /*hasDuplexCapability*/,
369 var selectedIndex = printerList.selectedIndex; 376 false /*defaultIsDuplexEnabled*/,
370 lastSelectedPrinterIndex = selectedIndex; 377 true /*hasOrientationCapability*/,
371 378 false /*defaultIsLandscapeEnabled*/,
372 // Regenerate the preview data based on selected printer settings. 379 true /*hasColorCapability*/,
373 // Do not reset the margins if no preview request has been made. 380 true /*defaultIsColorEnabled*/);
374 var resetMargins = lastPreviewRequestID != initialPreviewRequestID; 381 return dest;
375 setDefaultValuesAndRegeneratePreview(resetMargins); 382 },
376 } 383
377 384 /**
378 /** 385 * Prints the document or launches a pdf preview on the local system.
379 * Notifies listeners of |customEvents.PRINTER_CAPABILITIES_UPDATED| about the 386 * @param {boolean} isPdfPreview Whether to launch the pdf preview.
380 * capabilities of the currently selected printer. It is called from C++ too. 387 * @private
381 * @param {Object} settingInfo printer setting information. 388 */
382 */ 389 printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
383 function updateWithPrinterCapabilities(settingInfo) { 390 if (this.uiState_ != PrintPreview.UiState_.READY) {
384 var customEvent = new cr.Event(customEvents.PRINTER_CAPABILITIES_UPDATED); 391 throw Error(
385 customEvent.printerCapabilities = settingInfo; 392 'Print document request received when not in ready state: ' +
386 document.dispatchEvent(customEvent); 393 this.uiState_);
387 } 394 }
388 395 if (isPdfPreview) {
389 /** 396 this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;
390 * Reloads the printer list. 397 } else if (this.destinationStore_.selectedDestination.isPrintToPdf) {
391 */ 398 this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;
392 function reloadPrintersList() { 399 } else {
393 $('printer-list').length = 0; 400 this.uiState_ = PrintPreview.UiState_.PRINTING;
394 firstCloudPrintOptionPos = 0; 401 }
395 lastCloudPrintOptionPos = 0; 402 this.setIsEnabled_(false);
396 chrome.send('getPrinters'); 403 if (this.printIfReady_() &&
397 } 404 this.destinationStore_.selectedDestination.isLocal &&
398 405 !this.destinationStore_.selectedDestination.isPrintToPdf) {
399 /** 406 // Hide the dialog for now. The actual print command will be issued when
400 * Turn on the integration of Cloud Print. 407 // the preview generation is done.
401 * @param {string} cloudPrintURL The URL to use for cloud print servers. 408 this.nativeLayer_.startHideDialog();
402 */ 409 }
403 function setUseCloudPrint(cloudPrintURL) { 410 },
404 useCloudPrint = true; 411
405 cloudprint.setBaseURL(cloudPrintURL); 412 /**
406 } 413 * Attempts to print if needed and if ready.
407 414 * @return {boolean} Whether a print request was issued.
408 /** 415 * @private
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 printIfReady_: function() {
411 * @param {string} data Data to send as the print job. 418 if ((this.uiState_ == PrintPreview.UiState_.PRINTING ||
412 */ 419 this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||
413 function printToCloud(data) { 420 this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||
414 cloudprint.printToCloud(data, finishedCloudPrinting); 421 this.isInKioskAutoPrintMode_) &&
415 } 422 !this.isPreviewGenerationInProgress_ &&
416 423 this.destinationStore_.selectedDestination &&
417 /** 424 this.destinationStore_.selectedDestination.capabilities) {
418 * Cloud print upload of the PDF file is finished, time to close the dialog. 425 if (!this.printTicketStore_.isTicketValid()) {
419 */ 426 throw Error('Trying to print with invalid ticket');
420 function finishedCloudPrinting() { 427 }
421 closePrintPreviewTab(); 428 this.nativeLayer_.startSaveDestinationAndTicket(
422 } 429 this.destinationStore_.selectedDestination,
423 430 this.printTicketStore_);
424 /** 431 this.nativeLayer_.startPrint(
425 * Updates the fit to page option state based on the print scaling option of 432 this.destinationStore_.selectedDestination,
426 * source pdf. PDF's have an option to enable/disable print scaling. When we 433 this.printTicketStore_,
427 * find out that the print scaling option is disabled for the source pdf, we 434 this.cloudPrintInterface_);
428 * uncheck the fit to page checkbox. This function is called from C++ code. 435 return true;
429 */ 436 } else {
430 function printScalingDisabledForSourcePDF() { 437 return false;
431 fitToPageSettings.onPrintScalingDisabled(); 438 }
432 } 439 },
433 440
434 /** 441 /**
435 * Checks whether the specified settings are valid. 442 * Closes the print preview.
436 * 443 * @private
437 * @return {boolean} true if settings are valid, false if not. 444 */
438 */ 445 close_: function() {
439 function areSettingsValid() { 446 this.exitDocument();
440 var selectedPrinter = getSelectedPrinterName(); 447 this.uiState_ = PrintPreview.UiState_.CLOSING;
441 return pageSettings.isPageSelectionValid() && 448 this.nativeLayer_.startCloseDialog();
442 marginSettings.areMarginSettingsValid() && 449 },
443 (copiesSettings.isValid() || selectedPrinter == PRINT_TO_PDF || 450
444 selectedPrinter == PRINT_WITH_CLOUD_PRINT); 451 /**
445 } 452 * Opens the native system print dialog after disabling all controls.
446 453 * @private
447 /** 454 */
448 * Creates an object based on the values in the printer settings. 455 openSystemPrintDialog_: function() {
449 * 456 if (this.uiState_ != PrintPreview.UiState_.READY) {
450 * @return {Object} Object containing print job settings. 457 throw Error(
451 */ 458 'Request to open system dialog received when not in ready state: ' +
452 function getSettings() { 459 this.uiState_);
453 var deviceName = getSelectedPrinterName(); 460 }
454 var printToPDF = deviceName == PRINT_TO_PDF; 461 this.setIsEnabled_(false);
455 var printWithCloudPrint = deviceName == PRINT_WITH_CLOUD_PRINT; 462 this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
456 463 this.nativeLayer_.startShowSystemDialog();
457 var settings = 464 },
458 {'deviceName': deviceName, 465
459 'pageRange': pageSettings.selectedPageRanges, 466 /**
460 'duplex': copiesSettings.duplexMode, 467 * Window onload handler, sets up the page and starts print preview by
461 'copies': copiesSettings.numberOfCopies, 468 * getting the printer list.
462 'collate': copiesSettings.isCollated(), 469 * @private
463 'landscape': layoutSettings.isLandscape(), 470 */
464 'color': colorSettings.colorMode, 471 onWindowLoad_: function() {
465 'printToPDF': printToPDF, 472 this.decorate($('print-preview'));
466 'printWithCloudPrint': printWithCloudPrint, 473 i18nTemplate.process(document, templateData);
467 'isFirstRequest' : false, 474 if (!this.previewArea_.hasCompatiblePlugin) {
468 'headerFooterEnabled': headerFooterSettings.hasHeaderFooter(), 475 this.setIsEnabled_(false);
469 'marginsType': marginSettings.selectedMarginsValue, 476 }
470 'requestID': -1, 477 this.nativeLayer_.startGetInitialSettings();
471 'generateDraftData': generateDraftData, 478 },
472 'fitToPageEnabled': fitToPageSettings.hasFitToPage(), 479
473 'previewModifiable': previewModifiable}; 480 /**
474 481 * Called when the native layer has initial settings to set. Sets the
475 if (marginSettings.isCustomMarginsSelected()) 482 * initial settings of the print preview and begins fetching print
476 settings['marginsCustom'] = marginSettings.customMargins; 483 * destinations.
477 484 * @param {cr.Event} event Contains the initial print preview settings
478 var printerList = $('printer-list'); 485 * persisted through the session.
479 var selectedPrinter = printerList.selectedIndex; 486 * @private
480 if (cloudprint.isCloudPrint(printerList.options[selectedPrinter])) { 487 */
481 settings['cloudPrintID'] = 488 onInitialSettingsSet_: function(event) {
482 printerList.options[selectedPrinter].value; 489 if (this.uiState_ != PrintPreview.UiState_.INITIALIZING) {
483 } 490 throw Error(
484 return settings; 491 'Updating initial settings when not in initializing state: ' +
485 } 492 this.uiState_);
486 493 }
487 /** 494 this.uiState_ = PrintPreview.UiState_.READY;
488 * Creates an object based on the values in the printer settings. 495
489 * Note: |lastPreviewRequestID| is being modified every time this function is 496 this.isInKioskAutoPrintMode_ =
490 * called. Only call this function when a preview request is actually sent, 497 event.initialSettings.isInKioskAutoPrintMode;
491 * otherwise (for example when debugging) call getSettings(). 498 this.destinationStore_.initialDestinationId =
492 * 499 event.initialSettings.initialDestinationId;
493 * @return {Object} Object containing print job settings. 500 this.printTicketStore_.initialize(
494 */ 501 event.initialSettings.isDocumentModifiable,
495 function getSettingsWithRequestID() { 502 event.initialSettings.isDuplexEnabled,
496 var settings = getSettings(); 503 event.initialSettings.isHeaderFooterEnabled,
497 settings.requestID = generatePreviewRequestID(); 504 event.initialSettings.marginsType,
498 settings.isFirstRequest = isFirstPreviewRequest(); 505 event.initialSettings.customMargins,
499 return settings; 506 event.initialSettings.thousandsDelimeter,
500 } 507 event.initialSettings.decimalDelimeter,
501 508 event.initialSettings.unitType);
502 /** 509
503 * @return {number} The next unused preview request id. 510 this.nativeLayer_.startGetLocalDestinations();
504 */ 511 },
505 function generatePreviewRequestID() { 512
506 return ++lastPreviewRequestID; 513 /**
507 } 514 * Calls when the native layer enables Google Cloud Print integration.
508 515 * Fetches the user's cloud printers.
509 /** 516 * @param {cr.Event} event Contains the base URL of the Google Cloud Print
510 * @return {boolean} True iff a preview has been requested. 517 * service.
511 */ 518 * @private
512 function hasRequestedPreview() { 519 */
513 return lastPreviewRequestID != initialPreviewRequestID; 520 onCloudPrintEnable_: function(event) {
514 } 521 this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
515 522 event.baseCloudPrintUrl);
516 /** 523 this.tracker.add(
517 * @return {boolean} True if |lastPreviewRequestID| corresponds to the initial 524 this.cloudPrintInterface_,
518 * preview request. 525 cloudprint.CloudPrintInterface.EventType.SEARCH_DONE,
519 */ 526 this.onCloudPrintSearchDone_.bind(this));
520 function isFirstPreviewRequest() { 527 this.tracker.add(
521 return lastPreviewRequestID == initialPreviewRequestID + 1; 528 this.cloudPrintInterface_,
522 } 529 cloudprint.CloudPrintInterface.EventType.PRINTER_DONE,
523 530 this.onCloudPrintPrinterDone_.bind(this));
524 /** 531 this.tracker.add(
525 * Checks if |previewResponseId| matches |lastPreviewRequestId|. Used to ignore 532 this.cloudPrintInterface_,
526 * obsolete preview data responses. 533 cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,
527 * @param {number} previewResponseId The id to check. 534 this.onCloudPrintSubmitDone_.bind(this));
528 * @return {boolean} True if previewResponseId reffers to the expected response. 535 this.tracker.add(
529 */ 536 this.cloudPrintInterface_,
530 function isExpectedPreviewResponse(previewResponseId) { 537 cloudprint.CloudPrintInterface.EventType.ERROR,
531 return lastPreviewRequestID == previewResponseId; 538 this.onCloudPrintError_.bind(this));
532 } 539
533 540 var printWithCloudPrintDest =
534 /** 541 this.createPrintWithCloudPrintDestination_();
535 * Returns the name of the selected printer or the empty string if no 542 this.destinationStore_.insertDestination(printWithCloudPrintDest);
536 * printer is selected. 543
537 * @return {string} The name of the currently selected printer. 544 if (cr.isChromeOS) {
538 */ 545 this.cloudPrintInterface_.search(true /*isRecent*/);
539 function getSelectedPrinterName() { 546 this.fetchState_ |= PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS;
540 var printerList = $('printer-list'); 547 }
541 var selectedPrinter = printerList.selectedIndex; 548 },
542 if (selectedPrinter < 0) 549
543 return ''; 550 /**
544 return printerList.options[selectedPrinter].value; 551 * Called when the native layer gets local destinations. Adds local
545 } 552 * destination objects received from the operating system to the destination
546 553 * store. Also adds a print-to-pdf printer.
kmadhusu 2012/05/18 20:13:46 nit: Is it print-to-pdf or save-to-pdf?? Please fo
547 /** 554 * @param {cr.Event} Contains the local destinations to set.
548 * Asks the browser to print the preview PDF based on current print 555 * @private
549 * settings. If the preview is still loading, printPendingFile() will get 556 */
550 * called once the preview loads. 557 onLocalDestinationsSet_: function(event) {
551 */ 558 var localDestinations = [];
552 function requestToPrintDocument() { 559 for (var destInfo, i = 0; destInfo = event.destinationInfos[i]; i++) {
553 hasPendingPrintDocumentRequest = !isPrintReadyMetafileReady; 560 localDestinations.push(
554 var selectedPrinterName = getSelectedPrinterName(); 561 print_preview.LocalDestinationParser.parse(destInfo));
555 var printToPDF = selectedPrinterName == PRINT_TO_PDF; 562 }
556 var printWithCloudPrint = selectedPrinterName == PRINT_WITH_CLOUD_PRINT; 563 localDestinations.push(this.createLocalPdfPrintDestination_());
557 if (hasPendingPrintDocumentRequest) { 564 this.destinationStore_.insertDestinations(localDestinations);
558 if (previewAppRequested) { 565 this.fetchState_ &= ~PrintPreview.FetchState_.LOCAL_DESTINATIONS;
559 previewArea.showCustomMessage( 566 },
567
568 /**
569 * Called when the native layer retrieves the capabilities for the selected
570 * local destination.
571 * @param {cr.Event} event Contains the capabilities of the local print
572 * destination.
573 * @private
574 */
575 onLocalDestinationCapabilitiesSet_: function(event) {
576 // TODO There may be a race condition here. This method is assumed to
577 // return capabilities for the currently selected printer. But between the
578 // time the local printer was selected and the capabilities were
579 // retrieved, the selected printer can change. One way to address this is
580 // to include the destination ID in the settingsInfo parameter.
581 var selectedDestination = this.destinationStore_.selectedDestination;
582 if (selectedDestination.isLocal) {
583 var capabilities = print_preview.LocalCapabilitiesParser.parse(
584 event.settingsInfo);
585 selectedDestination.capabilities = capabilities;
586 this.printTicketStore_.updateDestinationCapabilities(capabilities);
587 this.printIfReady_();
588 }
589 },
590
591 /**
592 * Called from native layer after the user was requested to sign in, and did
593 * so successfully.
594 * @private
595 */
596 onDestinationsReload_: function() {
597 this.destinationStore_.clear();
598 this.nativeLayer_.startGetLocalDestinations();
599 if (this.cloudPrintInterface_) {
600 // Fetch recent printers.
601 this.cloudPrintInterface_.search(true /*isRecent*/);
602 // Fetch the full printer list.
603 this.cloudPrintInterface_.search(false /*isRecent*/);
604 }
605 this.fetchState_ =
606 PrintPreview.FetchState_.LOCAL_DESTINATIONS |
607 PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS |
608 PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS;
609 },
610
611 /**
612 * Called from the native layer when ready to print to Google Cloud Print.
613 * @param {cr.Event} event Contains the body to send in the HTTP request.
614 * @private
615 */
616 onPrintToCloud_: function(event) {
617 if (this.uiState_ != PrintPreview.UiState_.PRINTING) {
618 throw Error(
619 'Document ready to be sent to the cloud when not in printing ' +
620 'state: ' + this.uiState_);
621 }
622 if (this.cloudPrintInterface_) {
623 this.cloudPrintInterface_.submit(event.data);
624 } else {
625 throw Error('Google Cloud Print is not enabled');
626 }
627 },
628
629 /**
630 * Called from the native layer when the user cancels the save-to-pdf file
631 * selection dialog.
632 * @private
633 */
634 onFileSelectionCancel_: function() {
635 if (this.uiState_ != PrintPreview.UiState_.FILE_SELECTION) {
636 throw Error(
637 'File selection cancelled when not in file-selection state: ' +
638 this.uiState_);
639 }
640 this.setIsEnabled_(true);
641 this.uiState_ = PrintPreview.UiState_.READY;
642 },
643
644 /**
645 * Called from the native layer when save-to-pdf file selection is complete.
646 * @private
647 */
648 onFileSelectionComplete_: function() {
649 if (this.uiState_ != PrintPreview.UiState_.FILE_SELECTION) {
650 throw Error(
651 'File selection completed when not in file-selection state: ' +
652 this.uiState_);
653 }
654 this.previewArea_.showCustomMessage(
655 localStrings.getString('printingToPDFInProgress'));
656 this.uiState_ = PrintPreview.UiState_.PRINTING;
657 },
658
659 /**
660 * Called when the Google Cloud Print search API call completes. Adds
661 * destinations to the printer store and selects one if it matches the
662 * initial destination.
663 * @param {cr.Event} event Contains the new cloud destinations.
664 * @private
665 */
666 onCloudPrintSearchDone_: function(event) {
667 this.destinationStore_.insertDestinations(event.printers);
668 if (event.isRecent) {
669 this.fetchState_ &= ~PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS;
670 } else {
671 this.fetchState_ &= ~PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS;
672 }
673 },
674
675 /**
676 * Called when the Google Cloud Print printer API call completes. Updates
677 * the UI with the newly received capabilities.
678 * @param {cr.Event} event Contains the destination returned in the printer
679 * API call.
680 */
681 onCloudPrintPrinterDone_: function(event) {
682 var dest = this.destinationStore_.updateDestination(event.printer);
683 if (this.destinationStore_.selectedDestination == dest) {
684 this.printTicketStore_.updateDestinationCapabilities(dest.capabilities);
685 this.printIfReady_();
686 }
687 },
688
689 /**
690 * Called after successfully submitting a job to Google Cloud Print.
691 * @private
692 */
693 onCloudPrintSubmitDone_: function() {
694 if (this.uiState_ != PrintPreview.UiState_.PRINTING) {
695 throw Error(
696 'Submited job to Google Cloud Print but not in printing state ' +
697 this.uiState_);
698 }
699 this.close_();
700 },
701
702 /**
703 * Called when there was an error communicating with Google Cloud print.
704 * Displays an error message in the print header.
705 * @param {cr.Event} event Contains the error message.
706 * @private
707 */
708 onCloudPrintError_: function(event) {
709 if (cr.isChromeOS && event.message == '403') {
710 this.nativeLayer_.startCloudPrintSignIn();
711 } else {
712 this.printHeader_.setErrorMessage(event.message);
713 }
714 this.fetchState_ &=
715 ~PrintPreview.FetchState_.RECENT_CLOUD_DESTINATIONS &
716 ~PrintPreview.FetchState_.ALL_CLOUD_DESTINATIONS;
717 },
718
719 /**
720 * Called when a new destination has been selected. Fetches the
721 * destination's capability list.
722 * @private
723 */
724 onDestinationSelect_: function() {
725 var destination = this.destinationStore_.selectedDestination;
726
727 if (cr.isChromeOS && destination.isPrintWithCloudPrint) {
728 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
729 return;
730 }
731
732 // Fetch destination capabilities if necessary.
733 if (!destination.capabilities) {
734 if (destination.isLocal) {
735 this.nativeLayer_.startGetLocalDestinationCapabilities(
736 destination.id);
737 } else if (this.cloudPrintInterface_) {
738 this.cloudPrintInterface_.printer(destination.id);
739 } else {
740 // TODO Probably a cloud printer was initially selected, but cloud
741 // print is no longer available. Maybe default to the system's local
742 // default? What about Chrome OS?
743 throw Error(
744 'Selected destination is a cloud destination, but Google Cloud ' +
745 'Print is not enabled');
746 }
747 } else {
748 this.printTicketStore_.updateDestinationCapabilities(
749 destination.capabilities);
750 }
751
752 this.printIfReady_();
753 },
754
755 /**
756 * Called when the preview area's preview generation is in progress.
757 * @private
758 */
759 onPreviewGenerationInProgress_: function() {
760 this.isPreviewGenerationInProgress_ = true;
761 },
762
763 /**
764 * Called when the preview area's preview generation is complete.
765 * @private
766 */
767 onPreviewGenerationDone_: function() {
768 this.isPreviewGenerationInProgress_ = false;
769 this.printIfReady_();
770 },
771
772 /**
773 * Called when the preview area's preview failed to load.
774 * @private
775 */
776 onPreviewGenerationFail_: function() {
777 this.isPreviewGenerationInProgress_ = false;
778 if (this.uiState_ == PrintPreview.UiState_.PRINTING) {
779 this.nativeLayer_.startCancelPendingPrint();
780 }
781 },
782
783 onSystemDialogLinkClicked_: function() {
784 setIsVisible($('dialog-throbber'), true);
785 this.openSystemPrintDialog_();
786 },
787
788 /**
789 * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
790 * preview app.
791 * @private
792 */
793 onOpenPdfInPreviewLinkClick_: function() {
794 if (this.uiState_ != PrintPreview.UiState_.READY) {
795 throw Error(
796 'Trying to open pdf in preview when not in ready state: ' +
797 this.uiState_);
798 }
799 setIsVisible($('open-preview-app-throbber'), true);
800 this.previewArea_.showCustomMessage(
560 localStrings.getString('openingPDFInPreview')); 801 localStrings.getString('openingPDFInPreview'));
561 } else if (printToPDF) { 802 this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
562 sendPrintDocumentRequest(); 803 },
563 } else if (printWithCloudPrint) { 804
564 previewArea.showCustomMessage( 805 /**
565 localStrings.getString('printWithCloudPrintWait')); 806 * Called when the print header's print button is clicked. Prints the
566 disableInputElementsInSidebar(); 807 * document.
567 } else { 808 * @private
568 isTabHidden = true; 809 */
569 chrome.send('hidePreview'); 810 onPrintButtonClick_: function() {
811 if (this.uiState_ != PrintPreview.UiState_.READY) {
812 throw Error(
kmadhusu 2012/05/18 20:13:46 I see a lot of "throw Error()" statements in this
813 'Trying to print when not in ready state: ' + this.uiState_);
814 }
815 this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
816 },
817
818 /**
819 * Called when the print header's cancel button is clicked. Closes the
820 * print dialog.
821 * @private
822 */
823 onCancelButtonClick_: function() {
824 this.close_();
825 },
826
827 /**
828 * Consume escape key presses and ctrl + shift + p. Delegate everything else
829 * to the preview area.
830 * @param {KeyboardEvent} e The keyboard event.
831 * @private
832 */
833 onKeyDown_: function(e) {
834 // Escape key closes the dialog.
835 if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
836 !e.metaKey) {
837 this.close_();
838 e.preventDefault();
839 return;
840 }
841
842 // Ctrl + Shift + p / Mac equivalent.
843 if (e.keyCode == 80) {
844 if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
845 (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
846 this.openSystemPrintDialog_();
847 e.preventDefault();
848 return;
849 }
850 }
851
852 // Pass certain directional keyboard events to the PDF viewer.
853 this.previewArea_.handleDirectionalKeyEvent(e);
854 },
855
856 /**
857 * Called when native layer receives invalid settings for a print request.
858 * @private
859 */
860 onSettingsInvalid_: function() {
861 this.uiState_ = PrintPreview.UiState_.ERROR;
862 this.previewArea_.showCustomMessage(
863 localStrings.getString('invalidPrinterSettings'));
864 },
865
866 /**
867 * Called when the native layer dispatches a DISABLE_SCALING event. Updates
868 * the print ticket.
869 * @private
870 */
871 onDisableScaling_: function() {
872 this.printTicketStore_.updateFitToPage(false);
570 } 873 }
571 return; 874 };
572 } 875
573 876 // Export
574 if (printToPDF || previewAppRequested) { 877 return {
575 sendPrintDocumentRequest(); 878 PrintPreview: PrintPreview
576 } else { 879 };
577 window.setTimeout(function() { sendPrintDocumentRequest(); }, 1000); 880 });
578 } 881
579 } 882 // Pull in all other scripts in a single shot.
580 883 <include src="data/page_number_set.js"/>
581 /** 884 <include src="data/destination.js"/>
582 * Sends a message to cancel the pending print request. 885 <include src="data/local_parsers.js"/>
583 */ 886 <include src="data/cloud_parsers.js"/>
584 function cancelPendingPrintRequest() { 887 <include src="data/chromium_capabilities.js"/>
585 if (isTabHidden) 888 <include src="data/cloud_capabilities.js"/>
586 chrome.send('cancelPendingPrintRequest'); 889 <include src="data/destination_store.js"/>
587 } 890 <include src="data/margins.js"/>
588 891 <include src="data/document_info.js"/>
589 /** 892 <include src="data/printable_area.js"/>
590 * Sends a message to initiate print workflow. 893 <include src="data/measurement_system.js"/>
591 */ 894 <include src="data/print_ticket_store.js"/>
592 function sendPrintDocumentRequest() { 895 <include src="data/coordinate2d.js"/>
593 var printerList = $('printer-list'); 896 <include src="data/size.js"/>
594 var printer = printerList[printerList.selectedIndex]; 897 <include src="data/capabilities_holder.js"/>
595 chrome.send('saveLastPrinter', [printer.value, cloudprint.getData(printer)]); 898
596 899 <include src="data/ticket_items/ticket_item.js"/>
597 var settings = getSettings(); 900
598 if (cr.isMac && previewAppRequested) 901 <include src="data/ticket_items/custom_margins.js"/>
599 settings.OpenPDFInPreview = true; 902 <include src="data/ticket_items/collate.js"/>
600 903 <include src="data/ticket_items/color.js"/>
601 chrome.send('print', [JSON.stringify(settings), 904 <include src="data/ticket_items/copies.js"/>
602 cloudprint.getPrintTicketJSON(printer)]); 905 <include src="data/ticket_items/duplex.js"/>
603 } 906 <include src="data/ticket_items/header_footer.js"/>
604 907 <include src="data/ticket_items/landscape.js"/>
605 /** 908 <include src="data/ticket_items/margins_type.js"/>
606 * Loads the selected preview pages. 909 <include src="data/ticket_items/page_range.js"/>
607 */ 910 <include src="data/ticket_items/fit_to_page.js"/>
608 function loadSelectedPages() { 911
609 pageSettings.updatePageSelection(); 912 <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"/> 913 <include src="print_preview_animations.js"/>
1253 <include src="print_preview_cloud.js"/> 914 <include src="cloud_print_interface.js"/>
1254 <include src="print_preview_utils.js"/> 915 <include src="print_preview_utils.js"/>
1255 <include src="print_header.js"/> 916 <include src="print_header.js"/>
1256 <include src="page_settings.js"/> 917
1257 <include src="copies_settings.js"/> 918 <include src="settings/page_settings.js"/>
1258 <include src="header_footer_settings.js"/> 919 <include src="settings/copies_settings.js"/>
1259 <include src="fit_to_page_settings.js"/> 920 <include src="settings/layout_settings.js"/>
1260 <include src="layout_settings.js"/> 921 <include src="settings/color_settings.js"/>
1261 <include src="color_settings.js"/> 922 <include src="settings/margin_settings.js"/>
1262 <include src="margin_settings.js"/> 923 <include src="settings/destination_settings.js"/>
1263 <include src="margin_textbox.js"/> 924 <include src="settings/other_options_settings.js"/>
1264 <include src="margin_utils.js"/> 925
1265 <include src="margins_ui.js"/> 926 <include src="previewarea/margin_control.js"/>
1266 <include src="margins_ui_pair.js"/> 927 <include src="previewarea/margin_control_container.js"/>
1267 <include src="more_options.js"/> 928 <include src="previewarea/preview_area.js"/>
1268 <include src="preview_area.js"/> 929 <include src="preview_generator.js"/>
930
931 var printPreview = new print_preview.PrintPreview();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698