Bug 452317 - FeedConverter.js: QueryInterface should throw NS_ERROR_NO_INTERFACE...
[wine-gecko.git] / toolkit / components / printing / content / printUtils.js
bloba352106fffc244d2e750ae297d48ae36278a7d53
1 # -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 # ***** BEGIN LICENSE BLOCK *****
3 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 # The contents of this file are subject to the Mozilla Public License Version
6 # 1.1 (the "License"); you may not use this file except in compliance with
7 # the License. You may obtain a copy of the License at
8 # http://www.mozilla.org/MPL/
10 # Software distributed under the License is distributed on an "AS IS" basis,
11 # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 # for the specific language governing rights and limitations under the
13 # License.
15 # The Original Code is mozilla.org code.
17 # The Initial Developer of the Original Code is
18 # Netscape Communications Corporation.
19 # Portions created by the Initial Developer are Copyright (C) 1998
20 # the Initial Developer. All Rights Reserved.
22 # Contributor(s):
23 #   Blake Ross <blakeross@telocity.com>
24 #   Peter Annema <disttsc@bart.nl>
25 #   Samir Gehani <sgehani@netscape.com>
26 #   Pierre Chanial <p_ch@verizon.net>
28 # Alternatively, the contents of this file may be used under the terms of
29 # either the GNU General Public License Version 2 or later (the "GPL"), or
30 # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
31 # in which case the provisions of the GPL or the LGPL are applicable instead
32 # of those above. If you wish to allow use of your version of this file only
33 # under the terms of either the GPL or the LGPL, and not to allow others to
34 # use your version of this file under the terms of the MPL, indicate your
35 # decision by deleting the provisions above and replace them with the notice
36 # and other provisions required by the GPL or the LGPL. If you do not delete
37 # the provisions above, a recipient may use your version of this file under
38 # the terms of any one of the MPL, the GPL or the LGPL.
40 # ***** END LICENSE BLOCK *****
42 var gPrintSettingsAreGlobal = false;
43 var gSavePrintSettings = false;
44 var gFocusedElement = null;
46 var PrintUtils = {
48   showPageSetup: function ()
49   {
50     try {
51       var printSettings = this.getPrintSettings();
52       var PRINTPROMPTSVC = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
53                                      .getService(Components.interfaces.nsIPrintingPromptService);
54       PRINTPROMPTSVC.showPageSetup(window, printSettings, null);
55       if (gSavePrintSettings) {
56         // Page Setup data is a "native" setting on the Mac
57         var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
58                               .getService(Components.interfaces.nsIPrintSettingsService);
59         PSSVC.savePrintSettingsToPrefs(printSettings, true, printSettings.kInitSaveNativeData);
60       }
61     } catch (e) {
62       dump("showPageSetup "+e+"\n");
63       return false;
64     }
65     return true;
66   },
68   print: function (aWindow)
69   {
70     var webBrowserPrint = this.getWebBrowserPrint(aWindow);
71     var printSettings = this.getPrintSettings();
72     try {
73       webBrowserPrint.print(printSettings, null);
74       if (gPrintSettingsAreGlobal && gSavePrintSettings) {
75         var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
76                               .getService(Components.interfaces.nsIPrintSettingsService);
77         PSSVC.savePrintSettingsToPrefs(printSettings, true,
78                                        printSettings.kInitSaveAll);
79         PSSVC.savePrintSettingsToPrefs(printSettings, false,
80                                        printSettings.kInitSavePrinterName);
81       }
82     } catch (e) {
83       // Pressing cancel is expressed as an NS_ERROR_ABORT return value,
84       // causing an exception to be thrown which we catch here.
85       // Unfortunately this will also consume helpful failures, so add a
86       // dump("print: "+e+"\n"); // if you need to debug
87     }
88   },
90   // calling PrintUtils.printPreview() requires that you have three functions
91   // in the global scope: getPPBrowser(), which returns the browser element in
92   // the window print preview uses, getNavToolbox(), which returns the element
93   // (usually the main toolbox element) before which the print preview toolbar
94   // should be inserted, and getWebNavigation(), which returns the document's
95   // nsIWebNavigation object
96   printPreview: function (aEnterPPCallback, aExitPPCallback, aWindow)
97   {
98     // if we're already in PP mode, don't set the callbacks; chances
99     // are they're null because someone is calling printPreview() to
100     // get us to refresh the display.
101     var pptoolbar = document.getElementById("print-preview-toolbar");
102     if (!pptoolbar) {
103       this._onEnterPP = aEnterPPCallback;
104       this._onExitPP  = aExitPPCallback;
105     } else {
106       // collapse the browser here -- it will be shown in
107       // onEnterPrintPreview; this forces a reflow which fixes display
108       // issues in bug 267422.
109       var browser = getPPBrowser();
110       if (browser)
111         browser.collapsed = true;
112     }
114     this._webProgressPP = {};
115     var ppParams        = {};
116     var notifyOnOpen    = {};
117     var webBrowserPrint = this.getWebBrowserPrint(aWindow);
118     var printSettings   = this.getPrintSettings();
119     // Here we get the PrintingPromptService so we can display the PP Progress from script
120     // For the browser implemented via XUL with the PP toolbar we cannot let it be
121     // automatically opened from the print engine because the XUL scrollbars in the PP window
122     // will layout before the content window and a crash will occur.
123     // Doing it all from script, means it lays out before hand and we can let printing do it's own thing
124     var PPROMPTSVC = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
125                                .getService(Components.interfaces.nsIPrintingPromptService);
126     // just in case we are already printing, 
127     // an error code could be returned if the Prgress Dialog is already displayed
128     try {
129       PPROMPTSVC.showProgress(this, webBrowserPrint, printSettings, this._obsPP, false,
130                               this._webProgressPP, ppParams, notifyOnOpen);
131       if (ppParams.value) {
132         var webNav = getWebNavigation();
133         ppParams.value.docTitle = webNav.document.title;
134         ppParams.value.docURL   = webNav.currentURI.spec;
135       }
137       // this tells us whether we should continue on with PP or 
138       // wait for the callback via the observer
139       if (!notifyOnOpen.value.valueOf() || this._webProgressPP.value == null)
140         this.enterPrintPreview();
141     } catch (e) {
142       this.enterPrintPreview();
143     }
144   },
146   getWebBrowserPrint: function (aWindow)
147   {
148     var contentWindow = aWindow || window.content;
149     return contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
150                         .getInterface(Components.interfaces.nsIWebBrowserPrint);
151   },
153   ////////////////////////////////////////
154   // "private" methods. Don't use them. //
155   ////////////////////////////////////////
157   setPrinterDefaultsForSelectedPrinter: function (aPSSVC, aPrintSettings)
158   {
159     if (!aPrintSettings.printerName)
160       aPrintSettings.printerName = aPSSVC.defaultPrinterName;
162     // First get any defaults from the printer 
163     aPSSVC.initPrintSettingsFromPrinter(aPrintSettings.printerName, aPrintSettings);
164     // now augment them with any values from last time
165     aPSSVC.initPrintSettingsFromPrefs(aPrintSettings, true,  aPrintSettings.kInitSaveAll);
166   },
168   getPrintSettings: function ()
169   {
170     var pref = Components.classes["@mozilla.org/preferences-service;1"]
171                          .getService(Components.interfaces.nsIPrefBranch);
172     if (pref) {
173       gPrintSettingsAreGlobal = pref.getBoolPref("print.use_global_printsettings", false);
174       gSavePrintSettings = pref.getBoolPref("print.save_print_settings", false);
175     }
177     var printSettings;
178     try {
179       var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
180                             .getService(Components.interfaces.nsIPrintSettingsService);
181       if (gPrintSettingsAreGlobal) {
182         printSettings = PSSVC.globalPrintSettings;
183         this.setPrinterDefaultsForSelectedPrinter(PSSVC, printSettings);
184       } else {
185         printSettings = PSSVC.newPrintSettings;
186       }
187     } catch (e) {
188       dump("getPrintSettings: "+e+"\n");
189     }
190     return printSettings;
191   },
193   _closeHandlerPP: null,
194   _webProgressPP: null,
195   _onEnterPP: null,
196   _onExitPP: null,
198   // This observer is called once the progress dialog has been "opened"
199   _obsPP: 
200   {
201     observe: function(aSubject, aTopic, aData)
202     {
203       // delay the print preview to show the content of the progress dialog
204       setTimeout(function () { PrintUtils.enterPrintPreview(); }, 0);
205     },
207     QueryInterface : function(iid)
208     {
209       if (iid.equals(Components.interfaces.nsIObserver) ||
210           iid.equals(Components.interfaces.nsISupportsWeakReference) ||
211           iid.equals(Components.interfaces.nsISupports))
212         return this;   
213       throw Components.results.NS_NOINTERFACE;
214     }
215   },
217   enterPrintPreview: function (aWindow)
218   {
219     gFocusedElement = document.commandDispatcher.focusedElement;
221     var webBrowserPrint = this.getWebBrowserPrint(aWindow);
222     var printSettings   = this.getPrintSettings();
223     try {
224       webBrowserPrint.printPreview(printSettings, null, this._webProgressPP.value);
225     } catch (e) {
226       // Pressing cancel is expressed as an NS_ERROR_ABORT return value,
227       // causing an exception to be thrown which we catch here.
228       // Unfortunately this will also consume helpful failures, so add a
229       // dump(e); // if you need to debug
230       return;
231     }
233     var printPreviewTB = document.getElementById("print-preview-toolbar");
234     if (printPreviewTB) {
235       printPreviewTB.updateToolbar();
236       var browser = getPPBrowser();
237       if (browser)
238         browser.collapsed = false;
239       return;
240     }
242     // show the toolbar after we go into print preview mode so
243     // that we can initialize the toolbar with total num pages
244     var XUL_NS =
245       "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
246     printPreviewTB = document.createElementNS(XUL_NS, "toolbar");
247     printPreviewTB.setAttribute("printpreview", true);
248     printPreviewTB.setAttribute("id", "print-preview-toolbar");
250     var navToolbox = getNavToolbox();
251     navToolbox.parentNode.insertBefore(printPreviewTB, navToolbox);
253     // copy the window close handler
254     if (document.documentElement.hasAttribute("onclose"))
255       this._closeHandlerPP = document.documentElement.getAttribute("onclose");
256     else
257       this._closeHandlerPP = null;
258     document.documentElement.setAttribute("onclose", "PrintUtils.exitPrintPreview(); return false;");
260     // disable chrome shortcuts...
261     window.addEventListener("keypress", this.onKeyPressPP, true);
263     var contentWindow = aWindow || window.content;
264     contentWindow.focus();
266     // on Enter PP Call back
267     if (this._onEnterPP) {
268       this._onEnterPP();
269       this._onEnterPP = null;
270     }
271   },
273   exitPrintPreview: function (aWindow)
274   {
275     window.removeEventListener("keypress", this.onKeyPressPP, true);
277     // restore the old close handler
278     document.documentElement.setAttribute("onclose", this._closeHandlerPP);
279     this._closeHandlerPP = null;
281     var webBrowserPrint = this.getWebBrowserPrint(aWindow);
282     webBrowserPrint.exitPrintPreview(); 
284     // remove the print preview toolbar
285     var printPreviewTB = document.getElementById("print-preview-toolbar");
286     getNavToolbox().parentNode.removeChild(printPreviewTB);
288     var contentWindow = aWindow || window.content;
289     contentWindow.focus();
291     var cmdDispatcher = document.commandDispatcher;
292     cmdDispatcher.suppressFocusScroll = true;
293     if (gFocusedElement instanceof HTMLElement ||
294         gFocusedElement instanceof XULElement ||
295         gFocusedElement instanceof Window) {
296       gFocusedElement.focus();
297     }
298     else if (gFocusedElement instanceof Node) {
299       var content = window.content;
300       if (content instanceof Components.interfaces.nsIInterfaceRequestor)
301         content.getInterface(Components.interfaces.nsIDOMWindowUtils).focus(gFocusedElement);
302       }
303     gFocusedElement = null;
304     cmdDispatcher.suppressFocusScroll = false;
306     // on Exit PP Call back
307     if (this._onExitPP) {
308       this._onExitPP();
309       this._onExitPP = null;
310     }
311   },
313   onKeyPressPP: function (aEvent)
314   {
315     var closeKey;
316     try {
317       closeKey = document.getElementById("key_close")
318                          .getAttribute("key");
319       closeKey = aEvent["DOM_VK_"+closeKey];
320     } catch (e) {}
321     var isModif = aEvent.ctrlKey || aEvent.metaKey;
322     // ESC and Ctrl-W exits the PP
323     if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE || isModif &&
324         (aEvent.charCode == closeKey || aEvent.charCode == closeKey + 32)) {
325       PrintUtils.exitPrintPreview();
326     }
327     else if (isModif) {
328       var printPreviewTB = document.getElementById("print-preview-toolbar");
329       var printKey = document.getElementById("printKb").getAttribute("key").toUpperCase();
330       var pressedKey = String.fromCharCode(aEvent.charCode).toUpperCase();
331       if (printKey == pressedKey) {
332           PrintUtils.print();
333       }
334     }
335     // cancel shortkeys
336     if (isModif) {
337       aEvent.preventDefault();
338       aEvent.stopPropagation();
339     }
340   }