import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,478 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var gDialog;
var paramBlock;
var gPrefs = null;
var gPrintService = null;
var gPrintSettings = null;
var gStringBundle = null;
var gDoingMetric = false;
var gPrintSettingsInterface = Components.interfaces.nsIPrintSettings;
var gDoDebug = false;
// ---------------------------------------------------
function initDialog()
{
gDialog = {};
gDialog.orientation = document.getElementById("orientation");
gDialog.portrait = document.getElementById("portrait");
gDialog.landscape = document.getElementById("landscape");
gDialog.printBG = document.getElementById("printBG");
gDialog.shrinkToFit = document.getElementById("shrinkToFit");
gDialog.marginGroup = document.getElementById("marginGroup");
gDialog.marginPage = document.getElementById("marginPage");
gDialog.marginTop = document.getElementById("marginTop");
gDialog.marginBottom = document.getElementById("marginBottom");
gDialog.marginLeft = document.getElementById("marginLeft");
gDialog.marginRight = document.getElementById("marginRight");
gDialog.topInput = document.getElementById("topInput");
gDialog.bottomInput = document.getElementById("bottomInput");
gDialog.leftInput = document.getElementById("leftInput");
gDialog.rightInput = document.getElementById("rightInput");
gDialog.hLeftOption = document.getElementById("hLeftOption");
gDialog.hCenterOption = document.getElementById("hCenterOption");
gDialog.hRightOption = document.getElementById("hRightOption");
gDialog.fLeftOption = document.getElementById("fLeftOption");
gDialog.fCenterOption = document.getElementById("fCenterOption");
gDialog.fRightOption = document.getElementById("fRightOption");
gDialog.scalingLabel = document.getElementById("scalingInput");
gDialog.scalingInput = document.getElementById("scalingInput");
gDialog.enabled = false;
gDialog.strings = new Array;
gDialog.strings["marginUnits.inches"] = document.getElementById("marginUnits.inches").childNodes[0].nodeValue;
gDialog.strings["marginUnits.metric"] = document.getElementById("marginUnits.metric").childNodes[0].nodeValue;
gDialog.strings["customPrompt.title"] = document.getElementById("customPrompt.title").childNodes[0].nodeValue;
gDialog.strings["customPrompt.prompt"] = document.getElementById("customPrompt.prompt").childNodes[0].nodeValue;
}
// ---------------------------------------------------
function isListOfPrinterFeaturesAvailable()
{
var has_printerfeatures = false;
try {
has_printerfeatures = gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".has_special_printerfeatures");
} catch (ex) {
}
return has_printerfeatures;
}
// ---------------------------------------------------
function checkDouble(element)
{
element.value = element.value.replace(/[^.0-9]/g, "");
}
// Theoretical paper width/height.
var gPageWidth = 8.5;
var gPageHeight = 11.0;
// ---------------------------------------------------
function setOrientation()
{
var selection = gDialog.orientation.selectedItem;
var style = "background-color:white;";
if ((selection == gDialog.portrait && gPageWidth > gPageHeight) ||
(selection == gDialog.landscape && gPageWidth < gPageHeight)) {
// Swap width/height.
var temp = gPageHeight;
gPageHeight = gPageWidth;
gPageWidth = temp;
}
var div = gDoingMetric ? 100 : 10;
style += "width:" + gPageWidth/div + unitString() + ";height:" + gPageHeight/div + unitString() + ";";
gDialog.marginPage.setAttribute( "style", style );
}
// ---------------------------------------------------
function unitString()
{
return (gPrintSettings.paperSizeUnit == gPrintSettingsInterface.kPaperSizeInches) ? "in" : "mm";
}
// ---------------------------------------------------
function checkMargin( value, max, other )
{
// Don't draw this margin bigger than permitted.
return Math.min(value, max - other.value);
}
// ---------------------------------------------------
function changeMargin( node )
{
// Correct invalid input.
checkDouble(node);
// Reset the margin height/width for this node.
var val = node.value;
var nodeToStyle;
var attr="width";
if ( node == gDialog.topInput ) {
nodeToStyle = gDialog.marginTop;
val = checkMargin( val, gPageHeight, gDialog.bottomInput );
attr = "height";
} else if ( node == gDialog.bottomInput ) {
nodeToStyle = gDialog.marginBottom;
val = checkMargin( val, gPageHeight, gDialog.topInput );
attr = "height";
} else if ( node == gDialog.leftInput ) {
nodeToStyle = gDialog.marginLeft;
val = checkMargin( val, gPageWidth, gDialog.rightInput );
} else {
nodeToStyle = gDialog.marginRight;
val = checkMargin( val, gPageWidth, gDialog.leftInput );
}
var style = attr + ":" + (val/10) + unitString() + ";";
nodeToStyle.setAttribute( "style", style );
}
// ---------------------------------------------------
function changeMargins()
{
changeMargin( gDialog.topInput );
changeMargin( gDialog.bottomInput );
changeMargin( gDialog.leftInput );
changeMargin( gDialog.rightInput );
}
// ---------------------------------------------------
function customize( node )
{
// If selection is now "Custom..." then prompt user for custom setting.
if ( node.value == 6 ) {
var prompter = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService( Components.interfaces.nsIPromptService );
var title = gDialog.strings["customPrompt.title"];
var promptText = gDialog.strings["customPrompt.prompt"];
var result = { value: node.custom };
var ok = prompter.prompt(window, title, promptText, result, null, { value: false } );
if ( ok ) {
node.custom = result.value;
}
}
}
// ---------------------------------------------------
function setHeaderFooter( node, value )
{
node.value= hfValueToId(value);
if (node.value == 6) {
// Remember current Custom... value.
node.custom = value;
} else {
// Start with empty Custom... value.
node.custom = "";
}
}
var gHFValues = new Array;
gHFValues["&T"] = 1;
gHFValues["&U"] = 2;
gHFValues["&D"] = 3;
gHFValues["&P"] = 4;
gHFValues["&PT"] = 5;
function hfValueToId(val)
{
if ( val in gHFValues ) {
return gHFValues[val];
}
if ( val.length ) {
return 6; // Custom...
}
return 0; // --blank--
}
function hfIdToValue(node)
{
var result = "";
switch ( parseInt( node.value ) ) {
case 0:
break;
case 1:
result = "&T";
break;
case 2:
result = "&U";
break;
case 3:
result = "&D";
break;
case 4:
result = "&P";
break;
case 5:
result = "&PT";
break;
case 6:
result = node.custom;
break;
}
return result;
}
function setPrinterDefaultsForSelectedPrinter()
{
if (gPrintSettings.printerName == "") {
gPrintSettings.printerName = gPrintService.defaultPrinterName;
}
// First get any defaults from the printer
gPrintService.initPrintSettingsFromPrinter(gPrintSettings.printerName, gPrintSettings);
// now augment them with any values from last time
gPrintService.initPrintSettingsFromPrefs(gPrintSettings, true, gPrintSettingsInterface.kInitSaveAll);
if (gDoDebug) {
dump("pagesetup/setPrinterDefaultsForSelectedPrinter: printerName='"+gPrintSettings.printerName+"', orientation='"+gPrintSettings.orientation+"'\n");
}
}
// ---------------------------------------------------
function loadDialog()
{
var print_orientation = 0;
var print_margin_top = 0.5;
var print_margin_left = 0.5;
var print_margin_bottom = 0.5;
var print_margin_right = 0.5;
try {
gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
gPrintService = Components.classes["@mozilla.org/gfx/printsettings-service;1"];
if (gPrintService) {
gPrintService = gPrintService.getService();
if (gPrintService) {
gPrintService = gPrintService.QueryInterface(Components.interfaces.nsIPrintSettingsService);
}
}
} catch (ex) {
dump("loadDialog: ex="+ex+"\n");
}
setPrinterDefaultsForSelectedPrinter();
gDialog.printBG.checked = gPrintSettings.printBGColors || gPrintSettings.printBGImages;
gDialog.shrinkToFit.checked = gPrintSettings.shrinkToFit;
gDialog.scalingLabel.disabled = gDialog.scalingInput.disabled = gDialog.shrinkToFit.checked;
var marginGroupLabel = gDialog.marginGroup.label;
if (gPrintSettings.paperSizeUnit == gPrintSettingsInterface.kPaperSizeInches) {
marginGroupLabel = marginGroupLabel.replace(/#1/, gDialog.strings["marginUnits.inches"]);
gDoingMetric = false;
} else {
marginGroupLabel = marginGroupLabel.replace(/#1/, gDialog.strings["marginUnits.metric"]);
// Also, set global page dimensions for A4 paper, in millimeters (assumes portrait at this point).
gPageWidth = 2100;
gPageHeight = 2970;
gDoingMetric = true;
}
gDialog.marginGroup.label = marginGroupLabel;
print_orientation = gPrintSettings.orientation;
print_margin_top = convertMarginInchesToUnits(gPrintSettings.marginTop, gDoingMetric);
print_margin_left = convertMarginInchesToUnits(gPrintSettings.marginLeft, gDoingMetric);
print_margin_right = convertMarginInchesToUnits(gPrintSettings.marginRight, gDoingMetric);
print_margin_bottom = convertMarginInchesToUnits(gPrintSettings.marginBottom, gDoingMetric);
if (gDoDebug) {
dump("print_orientation "+print_orientation+"\n");
dump("print_margin_top "+print_margin_top+"\n");
dump("print_margin_left "+print_margin_left+"\n");
dump("print_margin_right "+print_margin_right+"\n");
dump("print_margin_bottom "+print_margin_bottom+"\n");
}
if (print_orientation == gPrintSettingsInterface.kPortraitOrientation) {
gDialog.orientation.selectedItem = gDialog.portrait;
} else if (print_orientation == gPrintSettingsInterface.kLandscapeOrientation) {
gDialog.orientation.selectedItem = gDialog.landscape;
}
// Set orientation the first time on a timeout so the dialog sizes to the
// maximum height specified in the .xul file. Otherwise, if the user switches
// from landscape to portrait, the content grows and the buttons are clipped.
setTimeout( setOrientation, 0 );
gDialog.topInput.value = print_margin_top.toFixed(1);
gDialog.bottomInput.value = print_margin_bottom.toFixed(1);
gDialog.leftInput.value = print_margin_left.toFixed(1);
gDialog.rightInput.value = print_margin_right.toFixed(1);
changeMargins();
setHeaderFooter( gDialog.hLeftOption, gPrintSettings.headerStrLeft );
setHeaderFooter( gDialog.hCenterOption, gPrintSettings.headerStrCenter );
setHeaderFooter( gDialog.hRightOption, gPrintSettings.headerStrRight );
setHeaderFooter( gDialog.fLeftOption, gPrintSettings.footerStrLeft );
setHeaderFooter( gDialog.fCenterOption, gPrintSettings.footerStrCenter );
setHeaderFooter( gDialog.fRightOption, gPrintSettings.footerStrRight );
gDialog.scalingInput.value = (gPrintSettings.scaling * 100).toFixed(0);
// Enable/disable widgets based in the information whether the selected
// printer supports the matching feature or not
if (isListOfPrinterFeaturesAvailable()) {
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_orientation"))
gDialog.orientation.removeAttribute("disabled");
else
gDialog.orientation.setAttribute("disabled", "true");
}
// Give initial focus to the orientation radio group.
// Done on a timeout due to to bug 103197.
setTimeout( function() { gDialog.orientation.focus(); }, 0 );
}
// ---------------------------------------------------
function onLoad()
{
// Init gDialog.
initDialog();
if (window.arguments[0] != null) {
gPrintSettings = window.arguments[0].QueryInterface(Components.interfaces.nsIPrintSettings);
paramBlock = window.arguments[1].QueryInterface(Components.interfaces.nsIDialogParamBlock);
} else if (gDoDebug) {
alert("window.arguments[0] == null!");
}
// default return value is "cancel"
paramBlock.SetInt(0, 0);
if (gPrintSettings) {
loadDialog();
} else if (gDoDebug) {
alert("Could initialize gDialog, PrintSettings is null!");
}
}
function convertUnitsMarginToInches(aVal, aIsMetric)
{
if (aIsMetric) {
return aVal / 25.4;
}
return aVal;
}
function convertMarginInchesToUnits(aVal, aIsMetric)
{
if (aIsMetric) {
return aVal * 25.4;
}
return aVal;
}
// ---------------------------------------------------
function onAccept()
{
if (gPrintSettings) {
if ( gDialog.orientation.selectedItem == gDialog.portrait ) {
gPrintSettings.orientation = gPrintSettingsInterface.kPortraitOrientation;
} else {
gPrintSettings.orientation = gPrintSettingsInterface.kLandscapeOrientation;
}
// save these out so they can be picked up by the device spec
gPrintSettings.marginTop = convertUnitsMarginToInches(gDialog.topInput.value, gDoingMetric);
gPrintSettings.marginLeft = convertUnitsMarginToInches(gDialog.leftInput.value, gDoingMetric);
gPrintSettings.marginBottom = convertUnitsMarginToInches(gDialog.bottomInput.value, gDoingMetric);
gPrintSettings.marginRight = convertUnitsMarginToInches(gDialog.rightInput.value, gDoingMetric);
gPrintSettings.headerStrLeft = hfIdToValue(gDialog.hLeftOption);
gPrintSettings.headerStrCenter = hfIdToValue(gDialog.hCenterOption);
gPrintSettings.headerStrRight = hfIdToValue(gDialog.hRightOption);
gPrintSettings.footerStrLeft = hfIdToValue(gDialog.fLeftOption);
gPrintSettings.footerStrCenter = hfIdToValue(gDialog.fCenterOption);
gPrintSettings.footerStrRight = hfIdToValue(gDialog.fRightOption);
gPrintSettings.printBGColors = gDialog.printBG.checked;
gPrintSettings.printBGImages = gDialog.printBG.checked;
gPrintSettings.shrinkToFit = gDialog.shrinkToFit.checked;
var scaling = document.getElementById("scalingInput").value;
if (scaling < 10.0) {
scaling = 10.0;
}
if (scaling > 500.0) {
scaling = 500.0;
}
scaling /= 100.0;
gPrintSettings.scaling = scaling;
if (gDoDebug) {
dump("******* Page Setup Accepting ******\n");
dump("print_margin_top "+gDialog.topInput.value+"\n");
dump("print_margin_left "+gDialog.leftInput.value+"\n");
dump("print_margin_right "+gDialog.bottomInput.value+"\n");
dump("print_margin_bottom "+gDialog.rightInput.value+"\n");
}
}
// set return value to "ok"
if (paramBlock) {
paramBlock.SetInt(0, 1);
} else {
dump("*** FATAL ERROR: No paramBlock\n");
}
var flags = gPrintSettingsInterface.kInitSaveMargins |
gPrintSettingsInterface.kInitSaveHeaderLeft |
gPrintSettingsInterface.kInitSaveHeaderCenter |
gPrintSettingsInterface.kInitSaveHeaderRight |
gPrintSettingsInterface.kInitSaveFooterLeft |
gPrintSettingsInterface.kInitSaveFooterCenter |
gPrintSettingsInterface.kInitSaveFooterRight |
gPrintSettingsInterface.kInitSaveBGColors |
gPrintSettingsInterface.kInitSaveBGImages |
gPrintSettingsInterface.kInitSaveInColor |
gPrintSettingsInterface.kInitSaveReversed |
gPrintSettingsInterface.kInitSaveOrientation |
gPrintSettingsInterface.kInitSaveOddEvenPages |
gPrintSettingsInterface.kInitSaveShrinkToFit |
gPrintSettingsInterface.kInitSaveScaling;
gPrintService.savePrintSettingsToPrefs(gPrintSettings, true, flags);
return true;
}
// ---------------------------------------------------
function onCancel()
{
// set return value to "cancel"
if (paramBlock) {
paramBlock.SetInt(0, 0);
} else {
dump("*** FATAL ERROR: No paramBlock\n");
}
return true;
}

View file

@ -0,0 +1,234 @@
<?xml version="1.0"?> <!-- -*- Mode: HTML -*- -->
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://global/skin/printPageSetup.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://global/locale/printPageSetup.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
id="printPageSetupDialog"
onload="onLoad();"
ondialogaccept="return onAccept();"
oncancel="return onCancel();"
title="&printSetup.title;"
persist="screenX screenY"
screenX="24" screenY="24">
<script type="application/javascript" src="chrome://global/content/printPageSetup.js"/>
<!-- Localizable strings manipulated at run-time. -->
<data id="marginUnits.inches">&marginUnits.inches;</data>
<data id="marginUnits.metric">&marginUnits.metric;</data>
<data id="customPrompt.title">&customPrompt.title;</data>
<data id="customPrompt.prompt">&customPrompt.prompt;</data>
<tabbox flex="1">
<tabs>
<tab label="&basic.tab;"/>
<tab label="&advanced.tab;"/>
</tabs>
<tabpanels flex="1">
<vbox>
<groupbox>
<caption label="&formatGroup.label;"/>
<vbox>
<hbox align="center">
<label control="orientation" value="&orientation.label;"/>
<radiogroup id="orientation" oncommand="setOrientation()">
<hbox align="center">
<radio id="portrait"
class="portrait-page"
label="&portrait.label;"
accesskey="&portrait.accesskey;"/>
<radio id="landscape"
class="landscape-page"
label="&landscape.label;"
accesskey="&landscape.accesskey;"/>
</hbox>
</radiogroup>
</hbox>
<separator/>
<hbox align="center">
<label control="scalingInput"
value="&scale.label;"
accesskey="&scale.accesskey;"/>
<textbox id="scalingInput" size="4" oninput="checkDouble(this)"/>
<label value="&scalePercent;"/>
<separator/>
<checkbox id="shrinkToFit"
label="&shrinkToFit.label;"
accesskey="&shrinkToFit.accesskey;"
oncommand="gDialog.scalingInput.disabled=gDialog.scalingLabel.disabled=this.checked"/>
</hbox>
</vbox>
</groupbox>
<groupbox>
<caption label="&optionsGroup.label;"/>
<checkbox id="printBG"
label="&printBG.label;"
accesskey="&printBG.accesskey;"/>
</groupbox>
</vbox>
<vbox>
<groupbox>
<caption id="marginGroup" label="&marginGroup.label;"/>
<vbox>
<hbox align="center">
<spacer flex="1"/>
<label control="topInput"
value="&marginTop.label;"
accesskey="&marginTop.accesskey;"/>
<textbox id="topInput" size="5" oninput="changeMargin(this)"/>
<!-- This invisible label (with same content as the visible one!) is used
to ensure that the <textbox> is centered above the page. The same
technique is deployed for the bottom/left/right input fields, below. -->
<label value="&marginTop.label;" style="visibility: hidden;"/>
<spacer flex="1"/>
</hbox>
<hbox dir="ltr">
<spacer flex="1"/>
<vbox>
<spacer flex="1"/>
<label control="leftInput"
value="&marginLeft.label;"
accesskey="&marginLeft.accesskey;"/>
<textbox id="leftInput" size="5" oninput="changeMargin(this)"/>
<label value="&marginLeft.label;" style="visibility: hidden;"/>
<spacer flex="1"/>
</vbox>
<!-- The "margin page" draws a simulated printout page with dashed lines
for the margins. The height/width style attributes of the marginTop,
marginBottom, marginLeft, and marginRight elements are set by
the JS code dynamically based on the user input. -->
<vbox id="marginPage" style="height:29.7mm;">
<box id="marginTop" style="height:0.05in;"/>
<hbox flex="1" dir="ltr">
<box id="marginLeft" style="width:0.025in;"/>
<box style="border: 1px; border-style: dashed; border-color: gray;" flex="1"/>
<box id="marginRight" style="width:0.025in;"/>
</hbox>
<box id="marginBottom" style="height:0.05in;"/>
</vbox>
<vbox>
<spacer flex="1"/>
<label control="rightInput"
value="&marginRight.label;"
accesskey="&marginRight.accesskey;"/>
<textbox id="rightInput" size="5" oninput="changeMargin(this)"/>
<label value="&marginRight.label;" style="visibility: hidden;"/>
<spacer flex="1"/>
</vbox>
<spacer flex="1"/>
</hbox>
<hbox align="center">
<spacer flex="1"/>
<label control="bottomInput"
value="&marginBottom.label;"
accesskey="&marginBottom.accesskey;"/>
<textbox id="bottomInput" size="5" oninput="changeMargin(this)"/>
<label value="&marginBottom.label;" style="visibility: hidden;"/>
<spacer flex="1"/>
</hbox>
</vbox>
</groupbox>
<groupbox>
<caption id="headersAndFooters" label="&headerFooter.label;"/>
<grid>
<columns>
<column/>
<column/>
<column/>
</columns>
<rows>
<row dir="ltr">
<menulist id="hLeftOption" oncommand="customize(this)" tooltiptext="&headerLeft.tip;">
<menupopup>
<menuitem value="0" label="&hfBlank;"/>
<menuitem value="1" label="&hfTitle;"/>
<menuitem value="2" label="&hfURL;"/>
<menuitem value="3" label="&hfDateAndTime;"/>
<menuitem value="4" label="&hfPage;"/>
<menuitem value="5" label="&hfPageAndTotal;"/>
<menuitem value="6" label="&hfCustom;"/>
</menupopup>
</menulist>
<menulist id="hCenterOption" oncommand="customize(this)" tooltiptext="&headerCenter.tip;">
<menupopup>
<menuitem value="0" label="&hfBlank;"/>
<menuitem value="1" label="&hfTitle;"/>
<menuitem value="2" label="&hfURL;"/>
<menuitem value="3" label="&hfDateAndTime;"/>
<menuitem value="4" label="&hfPage;"/>
<menuitem value="5" label="&hfPageAndTotal;"/>
<menuitem value="6" label="&hfCustom;"/>
</menupopup>
</menulist>
<menulist id="hRightOption" oncommand="customize(this)" tooltiptext="&headerRight.tip;">
<menupopup>
<menuitem value="0" label="&hfBlank;"/>
<menuitem value="1" label="&hfTitle;"/>
<menuitem value="2" label="&hfURL;"/>
<menuitem value="3" label="&hfDateAndTime;"/>
<menuitem value="4" label="&hfPage;"/>
<menuitem value="5" label="&hfPageAndTotal;"/>
<menuitem value="6" label="&hfCustom;"/>
</menupopup>
</menulist>
</row>
<row dir="ltr">
<vbox align="center">
<label value="&hfLeft.label;"/>
</vbox>
<vbox align="center">
<label value="&hfCenter.label;"/>
</vbox>
<vbox align="center">
<label value="&hfRight.label;"/>
</vbox>
</row>
<row dir="ltr">
<menulist id="fLeftOption" oncommand="customize(this)" tooltiptext="&footerLeft.tip;">
<menupopup>
<menuitem value="0" label="&hfBlank;"/>
<menuitem value="1" label="&hfTitle;"/>
<menuitem value="2" label="&hfURL;"/>
<menuitem value="3" label="&hfDateAndTime;"/>
<menuitem value="4" label="&hfPage;"/>
<menuitem value="5" label="&hfPageAndTotal;"/>
<menuitem value="6" label="&hfCustom;"/>
</menupopup>
</menulist>
<menulist id="fCenterOption" oncommand="customize(this)" tooltiptext="&footerCenter.tip;">
<menupopup>
<menuitem value="0" label="&hfBlank;"/>
<menuitem value="1" label="&hfTitle;"/>
<menuitem value="2" label="&hfURL;"/>
<menuitem value="3" label="&hfDateAndTime;"/>
<menuitem value="4" label="&hfPage;"/>
<menuitem value="5" label="&hfPageAndTotal;"/>
<menuitem value="6" label="&hfCustom;"/>
</menupopup>
</menulist>
<menulist id="fRightOption" oncommand="customize(this)" tooltiptext="&footerRight.tip;">
<menupopup>
<menuitem value="0" label="&hfBlank;"/>
<menuitem value="1" label="&hfTitle;"/>
<menuitem value="2" label="&hfURL;"/>
<menuitem value="3" label="&hfDateAndTime;"/>
<menuitem value="4" label="&hfPage;"/>
<menuitem value="5" label="&hfPageAndTotal;"/>
<menuitem value="6" label="&hfCustom;"/>
</menupopup>
</menulist>
</row>
</rows>
</grid>
</groupbox>
</vbox>
</tabpanels>
</tabbox>
</dialog>

View file

@ -0,0 +1,415 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!-- this file depends on printUtils.js -->
<!DOCTYPE bindings [
<!ENTITY % printPreviewDTD SYSTEM "chrome://global/locale/printPreview.dtd" >
%printPreviewDTD;
]>
<bindings id="printPreviewBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<binding id="printpreviewtoolbar"
extends="chrome://global/content/bindings/toolbar.xml#toolbar">
<resources>
<stylesheet src="chrome://global/skin/printPreview.css"/>
</resources>
<content>
<xul:button label="&print.label;" accesskey="&print.accesskey;"
oncommand="this.parentNode.print();" icon="print"/>
<xul:button label="&pageSetup.label;" accesskey="&pageSetup.accesskey;"
oncommand="this.parentNode.doPageSetup();"/>
<xul:vbox align="center" pack="center">
<xul:label value="&page.label;" accesskey="&page.accesskey;" control="pageNumber"/>
</xul:vbox>
<xul:toolbarbutton anonid="navigateHome" class="navigate-button tabbable"
oncommand="parentNode.navigate(0, 0, 'home');" tooltiptext="&homearrow.tooltip;"/>
<xul:toolbarbutton anonid="navigatePrevious" class="navigate-button tabbable"
oncommand="parentNode.navigate(-1, 0, 0);" tooltiptext="&previousarrow.tooltip;"/>
<xul:hbox align="center" pack="center">
<xul:textbox id="pageNumber" size="3" value="1" min="1" type="number"
hidespinbuttons="true" onchange="navigate(0, this.valueNumber, 0);"/>
<xul:label value="&of.label;"/>
<xul:label value="1"/>
</xul:hbox>
<xul:toolbarbutton anonid="navigateNext" class="navigate-button tabbable"
oncommand="parentNode.navigate(1, 0, 0);" tooltiptext="&nextarrow.tooltip;"/>
<xul:toolbarbutton anonid="navigateEnd" class="navigate-button tabbable"
oncommand="parentNode.navigate(0, 0, 'end');" tooltiptext="&endarrow.tooltip;"/>
<xul:toolbarseparator class="toolbarseparator-primary"/>
<xul:vbox align="center" pack="center">
<xul:label value="&scale.label;" accesskey="&scale.accesskey;" control="scale"/>
</xul:vbox>
<xul:hbox align="center" pack="center">
<xul:menulist id="scale" crop="none"
oncommand="parentNode.parentNode.scale(this.selectedItem.value);">
<xul:menupopup>
<xul:menuitem value="0.3" label="&p30.label;"/>
<xul:menuitem value="0.4" label="&p40.label;"/>
<xul:menuitem value="0.5" label="&p50.label;"/>
<xul:menuitem value="0.6" label="&p60.label;"/>
<xul:menuitem value="0.7" label="&p70.label;"/>
<xul:menuitem value="0.8" label="&p80.label;"/>
<xul:menuitem value="0.9" label="&p90.label;"/>
<xul:menuitem value="1" label="&p100.label;"/>
<xul:menuitem value="1.25" label="&p125.label;"/>
<xul:menuitem value="1.5" label="&p150.label;"/>
<xul:menuitem value="1.75" label="&p175.label;"/>
<xul:menuitem value="2" label="&p200.label;"/>
<xul:menuseparator/>
<xul:menuitem flex="1" value="ShrinkToFit"
label="&ShrinkToFit.label;"/>
<xul:menuitem value="Custom" label="&Custom.label;"/>
</xul:menupopup>
</xul:menulist>
</xul:hbox>
<xul:toolbarseparator class="toolbarseparator-primary"/>
<xul:hbox align="center" pack="center">
<xul:toolbarbutton label="&portrait.label;" checked="true"
accesskey="&portrait.accesskey;"
type="radio" group="orient" class="toolbar-portrait-page tabbable"
oncommand="parentNode.parentNode.orient('portrait');"/>
<xul:toolbarbutton label="&landscape.label;"
accesskey="&landscape.accesskey;"
type="radio" group="orient" class="toolbar-landscape-page tabbable"
oncommand="parentNode.parentNode.orient('landscape');"/>
</xul:hbox>
<xul:toolbarseparator class="toolbarseparator-primary"/>
<xul:checkbox label="&simplifyPage.label;" checked="false" disabled="true"
accesskey="&simplifyPage.accesskey;"
tooltiptext-disabled="&simplifyPage.disabled.tooltip;"
tooltiptext-enabled="&simplifyPage.enabled.tooltip;"
oncommand="this.parentNode.simplify();"/>
<xul:toolbarseparator class="toolbarseparator-primary"/>
<xul:button label="&close.label;" accesskey="&close.accesskey;"
oncommand="PrintUtils.exitPrintPreview();" icon="close"/>
<xul:data value="&customPrompt.title;"/>
</content>
<implementation implements="nsIMessageListener">
<field name="mPrintButton">
document.getAnonymousNodes(this)[0]
</field>
<field name="mPageTextBox">
document.getAnonymousNodes(this)[5].childNodes[0]
</field>
<field name="mTotalPages">
document.getAnonymousNodes(this)[5].childNodes[2]
</field>
<field name="mScaleLabel">
document.getAnonymousNodes(this)[9].firstChild
</field>
<field name="mScaleCombobox">
document.getAnonymousNodes(this)[10].firstChild
</field>
<field name="mOrientButtonsBox">
document.getAnonymousNodes(this)[12]
</field>
<field name="mPortaitButton">
this.mOrientButtonsBox.childNodes[0]
</field>
<field name="mLandscapeButton">
this.mOrientButtonsBox.childNodes[1]
</field>
<field name="mSimplifyPageCheckbox">
document.getAnonymousNodes(this)[14]
</field>
<field name="mSimplifyPageToolbarSeparator">
document.getAnonymousNodes(this)[15]
</field>
<field name="mCustomTitle">
document.getAnonymousNodes(this)[17].firstChild
</field>
<field name="mPrintPreviewObs">
</field>
<field name="mWebProgress">
</field>
<field name="mPPBrowser">
null
</field>
<field name="mMessageManager">
null
</field>
<method name="initialize">
<parameter name="aPPBrowser"/>
<body>
<![CDATA[
let {Services} = Components.utils.import("resource://gre/modules/Services.jsm", {});
if (!Services.prefs.getBoolPref("print.use_simplify_page")) {
this.mSimplifyPageCheckbox.hidden = true;
this.mSimplifyPageToolbarSeparator.hidden = true;
}
this.mPPBrowser = aPPBrowser;
this.mMessageManager = aPPBrowser.messageManager;
this.mMessageManager.addMessageListener("Printing:Preview:UpdatePageCount", this);
this.updateToolbar();
let $ = id => document.getAnonymousElementByAttribute(this, "anonid", id);
let ltr = document.documentElement.matches(":root:-moz-locale-dir(ltr)");
// Windows 7 doesn't support ⏮ and ⏭ by default, and fallback doesn't
// always work (bug 1343330).
let {AppConstants} = Components.utils.import("resource://gre/modules/AppConstants.jsm", {});
let useCompatCharacters = AppConstants.isPlatformAndVersionAtMost("win", "6.1");
let leftEnd = useCompatCharacters ? "⏪" : "⏮";
let rightEnd = useCompatCharacters ? "⏩" : "⏭";
$("navigateHome").label = ltr ? leftEnd : rightEnd;
$("navigatePrevious").label = ltr ? "◂" : "▸";
$("navigateNext").label = ltr ? "▸" : "◂";
$("navigateEnd").label = ltr ? rightEnd : leftEnd;
]]>
</body>
</method>
<method name="doPageSetup">
<body>
<![CDATA[
var didOK = PrintUtils.showPageSetup();
if (didOK) {
// the changes that effect the UI
this.updateToolbar();
// Now do PrintPreview
PrintUtils.printPreview();
}
]]>
</body>
</method>
<method name="navigate">
<parameter name="aDirection"/>
<parameter name="aPageNum"/>
<parameter name="aHomeOrEnd"/>
<body>
<![CDATA[
const nsIWebBrowserPrint = Components.interfaces.nsIWebBrowserPrint;
let navType, pageNum;
// we use only one of aHomeOrEnd, aDirection, or aPageNum
if (aHomeOrEnd) {
// We're going to either the very first page ("home"), or the
// very last page ("end").
if (aHomeOrEnd == "home") {
navType = nsIWebBrowserPrint.PRINTPREVIEW_HOME;
this.mPageTextBox.value = 1;
} else {
navType = nsIWebBrowserPrint.PRINTPREVIEW_END;
this.mPageTextBox.value = this.mPageTextBox.max;
}
pageNum = 0;
} else if (aDirection) {
// aDirection is either +1 or -1, and allows us to increment
// or decrement our currently viewed page.
this.mPageTextBox.valueNumber += aDirection;
navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
pageNum = this.mPageTextBox.value; // TODO: back to valueNumber?
} else {
// We're going to a specific page (aPageNum)
navType = nsIWebBrowserPrint.PRINTPREVIEW_GOTO_PAGENUM;
pageNum = aPageNum;
}
this.mMessageManager.sendAsyncMessage("Printing:Preview:Navigate", {
navType: navType,
pageNum: pageNum,
});
]]>
</body>
</method>
<method name="print">
<body>
<![CDATA[
PrintUtils.printWindow(this.mPPBrowser.outerWindowID, this.mPPBrowser);
]]>
</body>
</method>
<method name="promptForScaleValue">
<parameter name="aValue"/>
<body>
<![CDATA[
var value = Math.round(aValue);
var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
var promptStr = this.mScaleLabel.value;
var renameTitle = this.mCustomTitle;
var result = {value:value};
var confirmed = promptService.prompt(window, renameTitle, promptStr, result, null, {value:value});
if (!confirmed || (!result.value) || (result.value == "") || result.value == value) {
return -1;
}
return result.value;
]]>
</body>
</method>
<method name="setScaleCombobox">
<parameter name="aValue"/>
<body>
<![CDATA[
var scaleValues = [0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1, 1.25, 1.5, 1.75, 2];
aValue = new Number(aValue);
for (var i = 0; i < scaleValues.length; i++) {
if (aValue == scaleValues[i]) {
this.mScaleCombobox.selectedIndex = i;
return;
}
}
this.mScaleCombobox.value = "Custom";
]]>
</body>
</method>
<method name="scale">
<parameter name="aValue"/>
<body>
<![CDATA[
var settings = PrintUtils.getPrintSettings();
if (aValue == "ShrinkToFit") {
if (!settings.shrinkToFit) {
settings.shrinkToFit = true;
this.savePrintSettings(settings, settings.kInitSaveShrinkToFit | settings.kInitSaveScaling);
PrintUtils.printPreview();
}
return;
}
if (aValue == "Custom") {
aValue = this.promptForScaleValue(settings.scaling * 100.0);
if (aValue >= 10) {
aValue /= 100.0;
} else {
if (this.mScaleCombobox.hasAttribute('lastValidInx')) {
this.mScaleCombobox.selectedIndex = this.mScaleCombobox.getAttribute('lastValidInx');
}
return;
}
}
this.setScaleCombobox(aValue);
this.mScaleCombobox.setAttribute('lastValidInx', this.mScaleCombobox.selectedIndex);
if (settings.scaling != aValue || settings.shrinkToFit)
{
settings.shrinkToFit = false;
settings.scaling = aValue;
this.savePrintSettings(settings, settings.kInitSaveShrinkToFit | settings.kInitSaveScaling);
PrintUtils.printPreview();
}
]]>
</body>
</method>
<method name="orient">
<parameter name="aOrientation"/>
<body>
<![CDATA[
const kIPrintSettings = Components.interfaces.nsIPrintSettings;
var orientValue = (aOrientation == "portrait") ? kIPrintSettings.kPortraitOrientation :
kIPrintSettings.kLandscapeOrientation;
var settings = PrintUtils.getPrintSettings();
if (settings.orientation != orientValue)
{
settings.orientation = orientValue;
this.savePrintSettings(settings, settings.kInitSaveOrientation);
PrintUtils.printPreview();
}
]]>
</body>
</method>
<method name="simplify">
<body>
<![CDATA[
PrintUtils.setSimplifiedMode(this.mSimplifyPageCheckbox.checked);
PrintUtils.printPreview();
]]>
</body>
</method>
<method name="enableSimplifyPage">
<body>
<![CDATA[
this.mSimplifyPageCheckbox.disabled = false;
this.mSimplifyPageCheckbox.setAttribute("tooltiptext",
this.mSimplifyPageCheckbox.getAttribute("tooltiptext-enabled"));
]]>
</body>
</method>
<method name="disableSimplifyPage">
<body>
<![CDATA[
this.mSimplifyPageCheckbox.disabled = true;
this.mSimplifyPageCheckbox.setAttribute("tooltiptext",
this.mSimplifyPageCheckbox.getAttribute("tooltiptext-disabled"));
]]>
</body>
</method>
<method name="updateToolbar">
<body>
<![CDATA[
var settings = PrintUtils.getPrintSettings();
var isPortrait = settings.orientation == Components.interfaces.nsIPrintSettings.kPortraitOrientation;
this.mPortaitButton.checked = isPortrait;
this.mLandscapeButton.checked = !isPortrait;
if (settings.shrinkToFit) {
this.mScaleCombobox.value = "ShrinkToFit";
} else {
this.setScaleCombobox(settings.scaling);
}
this.mPageTextBox.value = 1;
this.mMessageManager.sendAsyncMessage("Printing:Preview:UpdatePageCount");
]]>
</body>
</method>
<method name="savePrintSettings">
<parameter name="settings"/>
<parameter name="flags"/>
<body><![CDATA[
var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
.getService(Components.interfaces.nsIPrintSettingsService);
PSSVC.savePrintSettingsToPrefs(settings, true, flags);
]]></body>
</method>
<!-- nsIMessageListener -->
<method name="receiveMessage">
<parameter name="message"/>
<body>
<![CDATA[
if (message.name == "Printing:Preview:UpdatePageCount") {
let numPages = message.data.numPages;
this.mTotalPages.value = numPages;
this.mPageTextBox.max = numPages;
}
]]>
</body>
</method>
</implementation>
</binding>
</bindings>

View file

@ -0,0 +1,154 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// dialog is just an array we'll use to store various properties from the dialog document...
var dialog;
// the printProgress is a nsIPrintProgress object
var printProgress = null;
// random global variables...
var targetFile;
var docTitle = "";
var docURL = "";
var progressParams = null;
function ellipseString(aStr, doFront)
{
if (aStr.length > 3 && (aStr.substr(0, 3) == "..." || aStr.substr(aStr.length-4, 3) == "..."))
return aStr;
var fixedLen = 64;
if (aStr.length <= fixedLen)
return aStr;
if (doFront)
return "..." + aStr.substr(aStr.length-fixedLen, fixedLen);
return aStr.substr(0, fixedLen) + "...";
}
// all progress notifications are done through the nsIWebProgressListener implementation...
var progressListener = {
onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus)
{
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
window.close();
},
onProgressChange: function (aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
{
if (!progressParams)
return;
var docTitleStr = ellipseString(progressParams.docTitle, false);
if (docTitleStr != docTitle) {
docTitle = docTitleStr;
dialog.title.value = docTitle;
}
var docURLStr = ellipseString(progressParams.docURL, true);
if (docURLStr != docURL && dialog.title != null) {
docURL = docURLStr;
if (docTitle == "")
dialog.title.value = docURLStr;
}
},
onLocationChange: function (aWebProgress, aRequest, aLocation, aFlags) {},
onSecurityChange: function (aWebProgress, aRequest, state) {},
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage)
{
if (aMessage)
dialog.title.setAttribute("value", aMessage);
},
QueryInterface: function (iid)
{
if (iid.equals(Components.interfaces.nsIWebProgressListener) || iid.equals(Components.interfaces.nsISupportsWeakReference))
return this;
throw Components.results.NS_NOINTERFACE;
}
}
function onLoad() {
// Set global variables.
printProgress = window.arguments[0];
if (window.arguments[1]) {
progressParams = window.arguments[1].QueryInterface(Components.interfaces.nsIPrintProgressParams)
if (progressParams) {
docTitle = ellipseString(progressParams.docTitle, false);
docURL = ellipseString(progressParams.docURL, true);
}
}
if (!printProgress) {
dump( "Invalid argument to printPreviewProgress.xul\n" );
window.close()
return;
}
dialog = {};
dialog.strings = new Array;
dialog.title = document.getElementById("dialog.title");
dialog.titleLabel = document.getElementById("dialog.titleLabel");
dialog.title.value = docTitle;
// set our web progress listener on the helper app launcher
printProgress.registerListener(progressListener);
// We need to delay the set title else dom will overwrite it
window.setTimeout(doneIniting, 100);
}
function onUnload()
{
if (!printProgress)
return;
try {
printProgress.unregisterListener(progressListener);
printProgress = null;
}
catch (e) {}
}
function getString (stringId) {
// Check if we've fetched this string already.
if (!(stringId in dialog.strings)) {
// Try to get it.
var elem = document.getElementById( "dialog.strings."+stringId);
try {
if (elem && elem.childNodes && elem.childNodes[0] &&
elem.childNodes[0].nodeValue)
dialog.strings[stringId] = elem.childNodes[0].nodeValue;
// If unable to fetch string, use an empty string.
else
dialog.strings[stringId] = "";
} catch (e) { dialog.strings[stringId] = ""; }
}
return dialog.strings[stringId];
}
// If the user presses cancel, tell the app launcher and close the dialog...
function onCancel ()
{
// Cancel app launcher.
try {
printProgress.processCanceledByUser = true;
}
catch (e) { return true; }
// don't Close up dialog by returning false, the backend will close the dialog when everything will be aborted.
return false;
}
function doneIniting()
{
// called by function timeout in onLoad
printProgress.doneIniting();
}

View file

@ -0,0 +1,42 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://global/locale/printPreviewProgress.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&printWindow.title;"
style="width: 36em;"
buttons="cancel"
oncancel="onCancel()"
onload="onLoad()"
onunload="onUnload()">
<script type="application/javascript" src="chrome://global/content/printPreviewProgress.js"/>
<grid flex="1">
<columns>
<column/>
<column/>
</columns>
<rows>
<row>
<hbox pack="end">
<label id="dialog.titleLabel" value="&title;"/>
</hbox>
<label id="dialog.title"/>
</row>
<row class="thin-separator">
<hbox pack="end">
<label id="dialog.progressSpaces" value="&progress;"/>
</hbox>
<label id="dialog.progressLabel" value="&preparing;"/>
</row>
</rows>
</grid>
</dialog>

View file

@ -0,0 +1,282 @@
// -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// dialog is just an array we'll use to store various properties from the dialog document...
var dialog;
// the printProgress is a nsIPrintProgress object
var printProgress = null;
// random global variables...
var targetFile;
var docTitle = "";
var docURL = "";
var progressParams = null;
var switchUI = true;
function ellipseString(aStr, doFront)
{
if (aStr.length > 3 && (aStr.substr(0, 3) == "..." || aStr.substr(aStr.length-4, 3) == "...")) {
return aStr;
}
var fixedLen = 64;
if (aStr.length > fixedLen) {
if (doFront) {
var endStr = aStr.substr(aStr.length-fixedLen, fixedLen);
return "..." + endStr;
}
var frontStr = aStr.substr(0, fixedLen);
return frontStr + "...";
}
return aStr;
}
// all progress notifications are done through the nsIWebProgressListener implementation...
var progressListener = {
onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus)
{
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START)
{
// Put progress meter in undetermined mode.
// dialog.progress.setAttribute( "value", 0 );
dialog.progress.setAttribute( "mode", "undetermined" );
}
if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP)
{
// we are done printing
// Indicate completion in title area.
var msg = getString( "printComplete" );
dialog.title.setAttribute("value", msg);
// Put progress meter at 100%.
dialog.progress.setAttribute( "value", 100 );
dialog.progress.setAttribute( "mode", "normal" );
var percentPrint = getString( "progressText" );
percentPrint = replaceInsert( percentPrint, 1, 100 );
dialog.progressText.setAttribute("value", percentPrint);
var fm = Components.classes["@mozilla.org/focus-manager;1"]
.getService(Components.interfaces.nsIFocusManager);
if (fm && fm.activeWindow == window) {
// This progress dialog is the currently active window. In
// this case we need to make sure that some other window
// gets focus before we close this dialog to work around the
// buggy Windows XP Fax dialog, which ends up parenting
// itself to the currently focused window and is unable to
// survive that window going away. What happens without this
// opener.focus() call on Windows XP is that the fax dialog
// is opened only to go away when this dialog actually
// closes (which can happen asynchronously, so the fax
// dialog just flashes once and then goes away), so w/o this
// fix, it's impossible to fax on Windows XP w/o manually
// switching focus to another window (or holding on to the
// progress dialog with the mouse long enough).
opener.focus();
}
window.close();
}
},
onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress)
{
if (switchUI)
{
dialog.tempLabel.setAttribute("hidden", "true");
dialog.progress.setAttribute("hidden", "false");
var progressLabel = getString("progress");
if (progressLabel == "") {
progressLabel = "Progress:"; // better than nothing
}
switchUI = false;
}
if (progressParams)
{
var docTitleStr = ellipseString(progressParams.docTitle, false);
if (docTitleStr != docTitle) {
docTitle = docTitleStr;
dialog.title.value = docTitle;
}
var docURLStr = progressParams.docURL;
if (docURLStr != docURL && dialog.title != null) {
docURL = docURLStr;
if (docTitle == "") {
dialog.title.value = ellipseString(docURLStr, true);
}
}
}
// Calculate percentage.
var percent;
if ( aMaxTotalProgress > 0 )
{
percent = Math.round( (aCurTotalProgress*100)/aMaxTotalProgress );
if ( percent > 100 )
percent = 100;
dialog.progress.removeAttribute( "mode");
// Advance progress meter.
dialog.progress.setAttribute( "value", percent );
// Update percentage label on progress meter.
var percentPrint = getString( "progressText" );
percentPrint = replaceInsert( percentPrint, 1, percent );
dialog.progressText.setAttribute("value", percentPrint);
}
else
{
// Progress meter should be barber-pole in this case.
dialog.progress.setAttribute( "mode", "undetermined" );
// Update percentage label on progress meter.
dialog.progressText.setAttribute("value", "");
}
},
onLocationChange: function(aWebProgress, aRequest, aLocation, aFlags)
{
// we can ignore this notification
},
onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage)
{
if (aMessage != "")
dialog.title.setAttribute("value", aMessage);
},
onSecurityChange: function(aWebProgress, aRequest, state)
{
// we can ignore this notification
},
QueryInterface : function(iid)
{
if (iid.equals(Components.interfaces.nsIWebProgressListener) || iid.equals(Components.interfaces.nsISupportsWeakReference))
return this;
throw Components.results.NS_NOINTERFACE;
}
};
function getString( stringId ) {
// Check if we've fetched this string already.
if (!(stringId in dialog.strings)) {
// Try to get it.
var elem = document.getElementById( "dialog.strings."+stringId );
try {
if ( elem
&&
elem.childNodes
&&
elem.childNodes[0]
&&
elem.childNodes[0].nodeValue ) {
dialog.strings[stringId] = elem.childNodes[0].nodeValue;
} else {
// If unable to fetch string, use an empty string.
dialog.strings[stringId] = "";
}
} catch (e) { dialog.strings[stringId] = ""; }
}
return dialog.strings[stringId];
}
function loadDialog()
{
}
function replaceInsert( text, index, value ) {
var result = text;
var regExp = new RegExp( "#"+index );
result = result.replace( regExp, value );
return result;
}
function onLoad() {
// Set global variables.
printProgress = window.arguments[0];
if (window.arguments[1])
{
progressParams = window.arguments[1].QueryInterface(Components.interfaces.nsIPrintProgressParams)
if (progressParams)
{
docTitle = ellipseString(progressParams.docTitle, false);
docURL = ellipseString(progressParams.docURL, true);
}
}
if ( !printProgress ) {
dump( "Invalid argument to printProgress.xul\n" );
window.close()
return;
}
dialog = {};
dialog.strings = new Array;
dialog.title = document.getElementById("dialog.title");
dialog.titleLabel = document.getElementById("dialog.titleLabel");
dialog.progress = document.getElementById("dialog.progress");
dialog.progressText = document.getElementById("dialog.progressText");
dialog.progressLabel = document.getElementById("dialog.progressLabel");
dialog.tempLabel = document.getElementById("dialog.tempLabel");
dialog.progress.setAttribute("hidden", "true");
var progressLabel = getString("preparing");
if (progressLabel == "") {
progressLabel = "Preparing..."; // better than nothing
}
dialog.tempLabel.value = progressLabel;
dialog.title.value = docTitle;
// Fill dialog.
loadDialog();
// set our web progress listener on the helper app launcher
printProgress.registerListener(progressListener);
// We need to delay the set title else dom will overwrite it
window.setTimeout(doneIniting, 500);
}
function onUnload()
{
if (printProgress)
{
try
{
printProgress.unregisterListener(progressListener);
printProgress = null;
}
catch ( exception ) {}
}
}
// If the user presses cancel, tell the app launcher and close the dialog...
function onCancel ()
{
// Cancel app launcher.
try
{
printProgress.processCanceledByUser = true;
}
catch ( exception ) { return true; }
// don't Close up dialog by returning false, the backend will close the dialog when everything will be aborted.
return false;
}
function doneIniting()
{
printProgress.doneIniting();
}

View file

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE window SYSTEM "chrome://global/locale/printProgress.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="cancel"
title="&printWindow.title;"
style="width: 36em;"
ondialogcancel="onCancel()"
onload="onLoad()"
onunload="onUnload()">
<script type="application/javascript" src="chrome://global/content/printProgress.js"/>
<!-- This is non-visible content that simply adds translatable string
into the document so that it is accessible to JS code.
XXX-TODO:
convert to use string bundles.
-->
<data id="dialog.strings.dialogCloseLabel">&dialogClose.label;</data>
<data id="dialog.strings.printComplete">&printComplete;</data>
<data id="dialog.strings.progressText">&percentPrint;</data>
<data id="dialog.strings.progressLabel">&progress;</data>
<data id="dialog.strings.preparing">&preparing;</data>
<grid flex="1">
<columns>
<column/>
<column/>
<column/>
</columns>
<rows>
<row>
<hbox pack="end">
<label id="dialog.titleLabel" value="&title;"/>
</hbox>
<label id="dialog.title"/>
</row>
<row class="thin-separator">
<hbox pack="end">
<label id="dialog.progressLabel" control="dialog.progress" value="&progress;"/>
</hbox>
<label id="dialog.tempLabel" value="&preparing;"/>
<progressmeter id="dialog.progress" mode="normal" value="0"/>
<hbox pack="end" style="min-width: 2.5em;">
<label id="dialog.progressText"/>
</hbox>
</row>
</rows>
</grid>
</dialog>

View file

@ -0,0 +1,710 @@
// -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* PrintUtils is a utility for front-end code to trigger common print
* operations (printing, show print preview, show page settings).
*
* Unfortunately, likely due to inconsistencies in how different operating
* systems do printing natively, our XPCOM-level printing interfaces
* are a bit confusing and the method by which we do something basic
* like printing a page is quite circuitous.
*
* To compound that, we need to support remote browsers, and that means
* kicking off the print jobs in the content process. This means we send
* messages back and forth to that process. browser-content.js contains
* the object that listens and responds to the messages that PrintUtils
* sends.
*
* This also means that <xul:browser>'s that hope to use PrintUtils must have
* their type attribute set to either "content", "content-targetable", or
* "content-primary".
*
* PrintUtils sends messages at different points in its implementation, but
* their documentation is consolidated here for ease-of-access.
*
*
* Messages sent:
*
* Printing:Print
* Kick off a print job for a nsIDOMWindow, passing the outer window ID as
* windowID.
*
* Printing:Preview:Enter
* This message is sent to put content into print preview mode. We pass
* the content window of the browser we're showing the preview of, and
* the target of the message is the browser that we'll be showing the
* preview in.
*
* Printing:Preview:Exit
* This message is sent to take content out of print preview mode.
*
*
* Messages Received
*
* Printing:Preview:Entered
* This message is sent by the content process once it has completed
* putting the content into print preview mode. We must wait for that to
* to complete before switching the chrome UI to print preview mode,
* otherwise we have layout issues.
*
* Printing:Preview:StateChange, Printing:Preview:ProgressChange
* Due to a timing issue resulting in a main-process crash, we have to
* manually open the progress dialog for print preview. The progress
* dialog is opened here in PrintUtils, and then we listen for update
* messages from the child. Bug 1088061 has been filed to investigate
* other solutions.
*
*/
var gPrintSettingsAreGlobal = false;
var gSavePrintSettings = false;
var gFocusedElement = null;
var PrintUtils = {
init() {
window.messageManager.addMessageListener("Printing:Error", this);
},
get bundle() {
let stringService = Components.classes["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
delete this.bundle;
return this.bundle = stringService.createBundle("chrome://global/locale/printing.properties");
},
/**
* Shows the page setup dialog, and saves any settings changed in
* that dialog if print.save_print_settings is set to true.
*
* @return true on success, false on failure
*/
showPageSetup: function () {
try {
var printSettings = this.getPrintSettings();
var PRINTPROMPTSVC = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
.getService(Components.interfaces.nsIPrintingPromptService);
PRINTPROMPTSVC.showPageSetup(window, printSettings, null);
if (gSavePrintSettings) {
// Page Setup data is a "native" setting on the Mac
var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
.getService(Components.interfaces.nsIPrintSettingsService);
PSSVC.savePrintSettingsToPrefs(printSettings, true, printSettings.kInitSaveNativeData);
}
} catch (e) {
dump("showPageSetup "+e+"\n");
return false;
}
return true;
},
/**
* Starts the process of printing the contents of a window.
*
* @param aWindowID
* The outer window ID of the nsIDOMWindow to print.
* @param aBrowser
* The <xul:browser> that the nsIDOMWindow for aWindowID belongs to.
*/
printWindow: function (aWindowID, aBrowser)
{
let mm = aBrowser.messageManager;
mm.sendAsyncMessage("Printing:Print", {
windowID: aWindowID,
simplifiedMode: this._shouldSimplify,
});
},
/**
* Deprecated.
*
* Starts the process of printing the contents of window.content.
*
*/
print: function ()
{
if (gBrowser) {
return this.printWindow(gBrowser.selectedBrowser.outerWindowID,
gBrowser.selectedBrowser);
}
if (this.usingRemoteTabs) {
throw new Error("PrintUtils.print cannot be run in windows running with " +
"remote tabs. Use PrintUtils.printWindow instead.");
}
let domWindow = window.content;
let ifReq = domWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
let browser = ifReq.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.chromeEventHandler;
if (!browser) {
throw new Error("PrintUtils.print could not resolve content window " +
"to a browser.");
}
let windowID = ifReq.getInterface(Components.interfaces.nsIDOMWindowUtils)
.outerWindowID;
let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
let msg = "PrintUtils.print is now deprecated. Please use PrintUtils.printWindow.";
let url = "https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/Printing";
Deprecated.warning(msg, url);
this.printWindow(windowID, browser);
return undefined;
},
/**
* Initializes print preview.
*
* @param aListenerObj
* An object that defines the following functions:
*
* getPrintPreviewBrowser:
* Returns the <xul:browser> to display the print preview in. This
* <xul:browser> must have its type attribute set to "content",
* "content-targetable", or "content-primary".
*
* getSourceBrowser:
* Returns the <xul:browser> that contains the document being
* printed. This <xul:browser> must have its type attribute set to
* "content", "content-targetable", or "content-primary".
*
* getNavToolbox:
* Returns the primary toolbox for this window.
*
* onEnter:
* Called upon entering print preview.
*
* onExit:
* Called upon exiting print preview.
*
* These methods must be defined. printPreview can be called
* with aListenerObj as null iff this window is already displaying
* print preview (in which case, the previous aListenerObj passed
* to it will be used).
*/
printPreview: function (aListenerObj)
{
// if we're already in PP mode, don't set the listener; chances
// are it is null because someone is calling printPreview() to
// get us to refresh the display.
if (!this.inPrintPreview) {
this._listener = aListenerObj;
this._sourceBrowser = aListenerObj.getSourceBrowser();
this._originalTitle = this._sourceBrowser.contentTitle;
this._originalURL = this._sourceBrowser.currentURI.spec;
// Here we log telemetry data for when the user enters print preview.
this.logTelemetry("PRINT_PREVIEW_OPENED_COUNT");
} else {
// collapse the browser here -- it will be shown in
// enterPrintPreview; this forces a reflow which fixes display
// issues in bug 267422.
// We use the print preview browser as the source browser to avoid
// re-initializing print preview with a document that might now have changed.
this._sourceBrowser = this._listener.getPrintPreviewBrowser();
this._sourceBrowser.collapsed = true;
// If the user transits too quickly within preview and we have a pending
// progress dialog, we will close it before opening a new one.
this.ensureProgressDialogClosed();
}
this._webProgressPP = {};
let ppParams = {};
let notifyOnOpen = {};
let printSettings = this.getPrintSettings();
// Here we get the PrintingPromptService so we can display the PP Progress from script
// For the browser implemented via XUL with the PP toolbar we cannot let it be
// automatically opened from the print engine because the XUL scrollbars in the PP window
// will layout before the content window and a crash will occur.
// Doing it all from script, means it lays out before hand and we can let printing do its own thing
let PPROMPTSVC = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
.getService(Components.interfaces.nsIPrintingPromptService);
// just in case we are already printing,
// an error code could be returned if the Progress Dialog is already displayed
try {
PPROMPTSVC.showProgress(window, null, printSettings, this._obsPP, false,
this._webProgressPP, ppParams, notifyOnOpen);
if (ppParams.value) {
ppParams.value.docTitle = this._originalTitle;
ppParams.value.docURL = this._originalURL;
}
// this tells us whether we should continue on with PP or
// wait for the callback via the observer
if (!notifyOnOpen.value.valueOf() || this._webProgressPP.value == null) {
this.enterPrintPreview();
}
} catch (e) {
this.enterPrintPreview();
}
},
/**
* Returns the nsIWebBrowserPrint associated with some content window.
* This method is being kept here for compatibility reasons, but should not
* be called by code hoping to support e10s / remote browsers.
*
* @param aWindow
* The window from which to get the nsIWebBrowserPrint from.
* @return nsIWebBrowserPrint
*/
getWebBrowserPrint: function (aWindow)
{
let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
let text = "getWebBrowserPrint is now deprecated, and fully unsupported for " +
"multi-process browsers. Please use a frame script to get " +
"access to nsIWebBrowserPrint from content.";
let url = "https://developer.mozilla.org/en-US/docs/Printing_from_a_XUL_App";
Deprecated.warning(text, url);
if (this.usingRemoteTabs) {
return {};
}
var contentWindow = aWindow || window.content;
return contentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebBrowserPrint);
},
/**
* Returns the nsIWebBrowserPrint from the print preview browser's docShell.
* This method is being kept here for compatibility reasons, but should not
* be called by code hoping to support e10s / remote browsers.
*
* @return nsIWebBrowserPrint
*/
getPrintPreview: function() {
let Deprecated = Components.utils.import("resource://gre/modules/Deprecated.jsm", {}).Deprecated;
let text = "getPrintPreview is now deprecated, and fully unsupported for " +
"multi-process browsers. Please use a frame script to get " +
"access to nsIWebBrowserPrint from content.";
let url = "https://developer.mozilla.org/en-US/docs/Printing_from_a_XUL_App";
Deprecated.warning(text, url);
if (this.usingRemoteTabs) {
return {};
}
return this._listener.getPrintPreviewBrowser().docShell.printPreview;
},
get inPrintPreview() {
return document.getElementById("print-preview-toolbar") != null;
},
// "private" methods and members. Don't use them.
_listener: null,
_closeHandlerPP: null,
_webProgressPP: null,
_sourceBrowser: null,
_originalTitle: "",
_originalURL: "",
_shouldSimplify: false,
get usingRemoteTabs() {
// We memoize this, since it's highly unlikely to change over the lifetime
// of the window.
let usingRemoteTabs =
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsILoadContext)
.useRemoteTabs;
delete this.usingRemoteTabs;
return this.usingRemoteTabs = usingRemoteTabs;
},
displayPrintingError(nsresult, isPrinting) {
// The nsresults from a printing error are mapped to strings that have
// similar names to the errors themselves. For example, for error
// NS_ERROR_GFX_PRINTER_NO_PRINTER_AVAILABLE, the name of the string
// for the error message is: PERR_GFX_PRINTER_NO_PRINTER_AVAILABLE. What's
// more, if we're in the process of doing a print preview, it's possible
// that there are strings specific for print preview for these errors -
// if so, the names of those strings have _PP as a suffix. It's possible
// that no print preview specific strings exist, in which case it is fine
// to fall back to the original string name.
const MSG_CODES = [
"GFX_PRINTER_NO_PRINTER_AVAILABLE",
"GFX_PRINTER_NAME_NOT_FOUND",
"GFX_PRINTER_COULD_NOT_OPEN_FILE",
"GFX_PRINTER_STARTDOC",
"GFX_PRINTER_ENDDOC",
"GFX_PRINTER_STARTPAGE",
"GFX_PRINTER_DOC_IS_BUSY",
"ABORT",
"NOT_AVAILABLE",
"NOT_IMPLEMENTED",
"OUT_OF_MEMORY",
"UNEXPECTED",
];
// PERR_FAILURE is the catch-all error message if we've gotten one that
// we don't recognize.
msgName = "PERR_FAILURE";
for (let code of MSG_CODES) {
let nsErrorResult = "NS_ERROR_" + code;
if (Components.results[nsErrorResult] == nsresult) {
msgName = "PERR_" + code;
break;
}
}
let msg, title;
if (!isPrinting) {
// Try first with _PP suffix.
let ppMsgName = msgName + "_PP";
try {
msg = this.bundle.GetStringFromName(ppMsgName);
} catch (e) {
// We allow localizers to not have the print preview error string,
// and just fall back to the printing error string.
}
}
if (!msg) {
msg = this.bundle.GetStringFromName(msgName);
}
title = this.bundle.GetStringFromName(isPrinting ? "print_error_dialog_title"
: "printpreview_error_dialog_title");
let promptSvc = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
promptSvc.alert(window, title, msg);
},
receiveMessage(aMessage) {
if (aMessage.name == "Printing:Error") {
this.displayPrintingError(aMessage.data.nsresult,
aMessage.data.isPrinting);
return undefined;
}
// If we got here, then the message we've received must involve
// updating the print progress UI.
if (!this._webProgressPP.value) {
// We somehow didn't get a nsIWebProgressListener to be updated...
// I guess there's nothing to do.
return undefined;
}
let listener = this._webProgressPP.value;
let mm = aMessage.target.messageManager;
let data = aMessage.data;
switch (aMessage.name) {
case "Printing:Preview:ProgressChange": {
return listener.onProgressChange(null, null,
data.curSelfProgress,
data.maxSelfProgress,
data.curTotalProgress,
data.maxTotalProgress);
}
case "Printing:Preview:StateChange": {
if (data.stateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) {
// Strangely, the printing engine sends 2 STATE_STOP messages when
// print preview is finishing. One has the STATE_IS_DOCUMENT flag,
// the other has the STATE_IS_NETWORK flag. However, the webProgressPP
// listener stops listening once the first STATE_STOP is sent.
// Any subsequent messages result in NS_ERROR_FAILURE errors getting
// thrown. This should all get torn out once bug 1088061 is fixed.
mm.removeMessageListener("Printing:Preview:StateChange", this);
mm.removeMessageListener("Printing:Preview:ProgressChange", this);
}
return listener.onStateChange(null, null,
data.stateFlags,
data.status);
}
}
return undefined;
},
setPrinterDefaultsForSelectedPrinter: function (aPSSVC, aPrintSettings)
{
if (!aPrintSettings.printerName)
aPrintSettings.printerName = aPSSVC.defaultPrinterName;
// First get any defaults from the printer
aPSSVC.initPrintSettingsFromPrinter(aPrintSettings.printerName, aPrintSettings);
// now augment them with any values from last time
aPSSVC.initPrintSettingsFromPrefs(aPrintSettings, true, aPrintSettings.kInitSaveAll);
},
getPrintSettings: function ()
{
var pref = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch);
if (pref) {
gPrintSettingsAreGlobal = pref.getBoolPref("print.use_global_printsettings", false);
gSavePrintSettings = pref.getBoolPref("print.save_print_settings", false);
}
var printSettings;
try {
var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
.getService(Components.interfaces.nsIPrintSettingsService);
if (gPrintSettingsAreGlobal) {
printSettings = PSSVC.globalPrintSettings;
this.setPrinterDefaultsForSelectedPrinter(PSSVC, printSettings);
} else {
printSettings = PSSVC.newPrintSettings;
}
} catch (e) {
dump("getPrintSettings: "+e+"\n");
}
return printSettings;
},
// This observer is called once the progress dialog has been "opened"
_obsPP:
{
observe: function(aSubject, aTopic, aData)
{
// delay the print preview to show the content of the progress dialog
setTimeout(function () { PrintUtils.enterPrintPreview(); }, 0);
},
QueryInterface : function(iid)
{
if (iid.equals(Components.interfaces.nsIObserver) ||
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
iid.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
}
},
setSimplifiedMode: function (shouldSimplify)
{
this._shouldSimplify = shouldSimplify;
},
enterPrintPreview: function ()
{
// Send a message to the print preview browser to initialize
// print preview. If we happen to have gotten a print preview
// progress listener from nsIPrintingPromptService.showProgress
// in printPreview, we add listeners to feed that progress
// listener.
let ppBrowser = this._listener.getPrintPreviewBrowser();
let mm = ppBrowser.messageManager;
let sendEnterPreviewMessage = function (browser, simplified) {
mm.sendAsyncMessage("Printing:Preview:Enter", {
windowID: browser.outerWindowID,
simplifiedMode: simplified,
});
};
// If we happen to have gotten simplify page checked, we will lazily
// instantiate a new tab that parses the original page using ReaderMode
// primitives. When it's ready, and in order to enter on preview, we send
// over a message to print preview browser passing up the simplified tab as
// reference. If not, we pass the original tab instead as content source.
if (this._shouldSimplify) {
let simplifiedBrowser = this._listener.getSimplifiedSourceBrowser();
if (simplifiedBrowser) {
sendEnterPreviewMessage(simplifiedBrowser, true);
} else {
simplifiedBrowser = this._listener.createSimplifiedBrowser();
// After instantiating the simplified tab, we attach a listener as
// callback. Once we discover reader mode has been loaded, we fire
// up a message to enter on print preview.
let spMM = simplifiedBrowser.messageManager;
spMM.addMessageListener("Printing:Preview:ReaderModeReady", function onReaderReady() {
spMM.removeMessageListener("Printing:Preview:ReaderModeReady", onReaderReady);
sendEnterPreviewMessage(simplifiedBrowser, true);
});
// Here, we send down a message to simplified browser in order to parse
// the original page. After we have parsed it, content will tell parent
// that the document is ready for print previewing.
spMM.sendAsyncMessage("Printing:Preview:ParseDocument", {
URL: this._originalURL,
windowID: this._sourceBrowser.outerWindowID,
});
// Here we log telemetry data for when the user enters simplify mode.
this.logTelemetry("PRINT_PREVIEW_SIMPLIFY_PAGE_OPENED_COUNT");
}
} else {
sendEnterPreviewMessage(this._sourceBrowser, false);
}
if (this._webProgressPP.value) {
mm.addMessageListener("Printing:Preview:StateChange", this);
mm.addMessageListener("Printing:Preview:ProgressChange", this);
}
let onEntered = (message) => {
mm.removeMessageListener("Printing:Preview:Entered", onEntered);
if (message.data.failed) {
// Something went wrong while putting the document into print preview
// mode. Bail out.
this._listener.onEnter();
this._listener.onExit();
return;
}
// Stash the focused element so that we can return to it after exiting
// print preview.
gFocusedElement = document.commandDispatcher.focusedElement;
let printPreviewTB = document.getElementById("print-preview-toolbar");
if (printPreviewTB) {
printPreviewTB.updateToolbar();
ppBrowser.collapsed = false;
ppBrowser.focus();
return;
}
// Set the original window as an active window so any mozPrintCallbacks can
// run without delayed setTimeouts.
if (this._listener.activateBrowser) {
this._listener.activateBrowser(this._sourceBrowser);
} else {
this._sourceBrowser.docShellIsActive = true;
}
// show the toolbar after we go into print preview mode so
// that we can initialize the toolbar with total num pages
const XUL_NS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
printPreviewTB = document.createElementNS(XUL_NS, "toolbar");
printPreviewTB.setAttribute("printpreview", true);
printPreviewTB.setAttribute("fullscreentoolbar", true);
printPreviewTB.id = "print-preview-toolbar";
let navToolbox = this._listener.getNavToolbox();
navToolbox.parentNode.insertBefore(printPreviewTB, navToolbox);
printPreviewTB.initialize(ppBrowser);
// Enable simplify page checkbox when the page is an article
if (this._sourceBrowser.isArticle) {
printPreviewTB.enableSimplifyPage();
} else {
this.logTelemetry("PRINT_PREVIEW_SIMPLIFY_PAGE_UNAVAILABLE_COUNT");
printPreviewTB.disableSimplifyPage();
}
// copy the window close handler
if (document.documentElement.hasAttribute("onclose"))
this._closeHandlerPP = document.documentElement.getAttribute("onclose");
else
this._closeHandlerPP = null;
document.documentElement.setAttribute("onclose", "PrintUtils.exitPrintPreview(); return false;");
// disable chrome shortcuts...
window.addEventListener("keydown", this.onKeyDownPP, true);
window.addEventListener("keypress", this.onKeyPressPP, true);
ppBrowser.collapsed = false;
ppBrowser.focus();
// on Enter PP Call back
this._listener.onEnter();
};
mm.addMessageListener("Printing:Preview:Entered", onEntered);
},
exitPrintPreview: function ()
{
let ppBrowser = this._listener.getPrintPreviewBrowser();
let browserMM = ppBrowser.messageManager;
browserMM.sendAsyncMessage("Printing:Preview:Exit");
window.removeEventListener("keydown", this.onKeyDownPP, true);
window.removeEventListener("keypress", this.onKeyPressPP, true);
// restore the old close handler
document.documentElement.setAttribute("onclose", this._closeHandlerPP);
this._closeHandlerPP = null;
// remove the print preview toolbar
let printPreviewTB = document.getElementById("print-preview-toolbar");
this._listener.getNavToolbox().parentNode.removeChild(printPreviewTB);
let fm = Components.classes["@mozilla.org/focus-manager;1"]
.getService(Components.interfaces.nsIFocusManager);
if (gFocusedElement)
fm.setFocus(gFocusedElement, fm.FLAG_NOSCROLL);
else
this._sourceBrowser.focus();
gFocusedElement = null;
this.setSimplifiedMode(false);
this.ensureProgressDialogClosed();
this._listener.onExit();
},
logTelemetry: function (ID)
{
let histogram = Services.telemetry.getHistogramById(ID);
histogram.add(true);
},
onKeyDownPP: function (aEvent)
{
// Esc exits the PP
if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
PrintUtils.exitPrintPreview();
}
},
onKeyPressPP: function (aEvent)
{
var closeKey;
try {
closeKey = document.getElementById("key_close")
.getAttribute("key");
closeKey = aEvent["DOM_VK_"+closeKey];
} catch (e) {}
var isModif = aEvent.ctrlKey || aEvent.metaKey;
// Ctrl-W exits the PP
if (isModif &&
(aEvent.charCode == closeKey || aEvent.charCode == closeKey + 32)) {
PrintUtils.exitPrintPreview();
}
else if (isModif) {
var printPreviewTB = document.getElementById("print-preview-toolbar");
var printKey = document.getElementById("printKb").getAttribute("key").toUpperCase();
var pressedKey = String.fromCharCode(aEvent.charCode).toUpperCase();
if (printKey == pressedKey) {
printPreviewTB.print();
}
}
// cancel shortkeys
if (isModif) {
aEvent.preventDefault();
aEvent.stopPropagation();
}
},
/**
* If there's a printing or print preview progress dialog displayed, force
* it to close now.
*/
ensureProgressDialogClosed() {
if (this._webProgressPP && this._webProgressPP.value) {
this._webProgressPP.value.onStateChange(null, null,
Components.interfaces.nsIWebProgressListener.STATE_STOP, 0);
}
},
}
PrintUtils.init();

View file

@ -0,0 +1,425 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var dialog;
var printService = null;
var gOriginalNumCopies = 1;
var paramBlock;
var gPrefs = null;
var gPrintSettings = null;
var gWebBrowserPrint = null;
var gPrintSetInterface = Components.interfaces.nsIPrintSettings;
var doDebug = false;
// ---------------------------------------------------
function initDialog()
{
dialog = {};
dialog.propertiesButton = document.getElementById("properties");
dialog.descText = document.getElementById("descText");
dialog.printrangeGroup = document.getElementById("printrangeGroup");
dialog.allpagesRadio = document.getElementById("allpagesRadio");
dialog.rangeRadio = document.getElementById("rangeRadio");
dialog.selectionRadio = document.getElementById("selectionRadio");
dialog.frompageInput = document.getElementById("frompageInput");
dialog.frompageLabel = document.getElementById("frompageLabel");
dialog.topageInput = document.getElementById("topageInput");
dialog.topageLabel = document.getElementById("topageLabel");
dialog.numCopiesInput = document.getElementById("numCopiesInput");
dialog.printframeGroup = document.getElementById("printframeGroup");
dialog.aslaidoutRadio = document.getElementById("aslaidoutRadio");
dialog.selectedframeRadio = document.getElementById("selectedframeRadio");
dialog.eachframesepRadio = document.getElementById("eachframesepRadio");
dialog.printframeGroupLabel = document.getElementById("printframeGroupLabel");
dialog.fileCheck = document.getElementById("fileCheck");
dialog.printerLabel = document.getElementById("printerLabel");
dialog.printerList = document.getElementById("printerList");
dialog.printButton = document.documentElement.getButton("accept");
// <data> elements
dialog.printName = document.getElementById("printButton");
dialog.fpDialog = document.getElementById("fpDialog");
dialog.enabled = false;
}
// ---------------------------------------------------
function checkInteger(element)
{
var value = element.value;
if (value && value.length > 0) {
value = value.replace(/[^0-9]/g, "");
if (!value) value = "";
element.value = value;
}
if (!value || value < 1 || value > 999)
dialog.printButton.setAttribute("disabled", "true");
else
dialog.printButton.removeAttribute("disabled");
}
// ---------------------------------------------------
function stripTrailingWhitespace(element)
{
var value = element.value;
value = value.replace(/\s+$/, "");
element.value = value;
}
// ---------------------------------------------------
function getPrinterDescription(printerName)
{
var s = "";
try {
/* This may not work with non-ASCII test (see bug 235763 comment #16) */
s = gPrefs.getCharPref("print.printer_" + printerName + ".printer_description")
} catch (e) {
}
return s;
}
// ---------------------------------------------------
function listElement(aListElement)
{
this.listElement = aListElement;
}
listElement.prototype =
{
clearList:
function ()
{
// remove the menupopup node child of the menulist.
var popup = this.listElement.firstChild;
if (popup) {
this.listElement.removeChild(popup);
}
},
appendPrinterNames:
function (aDataObject)
{
if ((null == aDataObject) || !aDataObject.hasMore()) {
// disable dialog
this.listElement.setAttribute("value", "");
this.listElement.setAttribute("label",
document.getElementById("printingBundle")
.getString("noprinter"));
this.listElement.setAttribute("disabled", "true");
dialog.printerLabel.setAttribute("disabled", "true");
dialog.propertiesButton.setAttribute("disabled", "true");
dialog.fileCheck.setAttribute("disabled", "true");
dialog.printButton.setAttribute("disabled", "true");
}
else {
// build popup menu from printer names
var list = document.getElementById("printerList");
do {
printerNameStr = aDataObject.getNext();
list.appendItem(printerNameStr, printerNameStr, getPrinterDescription(printerNameStr));
} while (aDataObject.hasMore());
this.listElement.removeAttribute("disabled");
}
}
};
// ---------------------------------------------------
function getPrinters()
{
var selectElement = new listElement(dialog.printerList);
selectElement.clearList();
var printerEnumerator;
try {
printerEnumerator =
Components.classes["@mozilla.org/gfx/printerenumerator;1"]
.getService(Components.interfaces.nsIPrinterEnumerator)
.printerNameList;
} catch (e) { printerEnumerator = null; }
selectElement.appendPrinterNames(printerEnumerator);
selectElement.listElement.value = printService.defaultPrinterName;
// make sure we load the prefs for the initially selected printer
setPrinterDefaultsForSelectedPrinter();
}
// ---------------------------------------------------
// update gPrintSettings with the defaults for the selected printer
function setPrinterDefaultsForSelectedPrinter()
{
gPrintSettings.printerName = dialog.printerList.value;
dialog.descText.value = getPrinterDescription(gPrintSettings.printerName);
// First get any defaults from the printer
printService.initPrintSettingsFromPrinter(gPrintSettings.printerName, gPrintSettings);
// now augment them with any values from last time
printService.initPrintSettingsFromPrefs(gPrintSettings, true, gPrintSetInterface.kInitSaveAll);
if (doDebug) {
dump("setPrinterDefaultsForSelectedPrinter: printerName='"+gPrintSettings.printerName+"', paperName='"+gPrintSettings.paperName+"'\n");
}
}
// ---------------------------------------------------
function displayPropertiesDialog()
{
gPrintSettings.numCopies = dialog.numCopiesInput.value;
try {
var printingPromptService = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
.getService(Components.interfaces.nsIPrintingPromptService);
if (printingPromptService) {
printingPromptService.showPrinterProperties(null, dialog.printerList.value, gPrintSettings);
dialog.numCopiesInput.value = gPrintSettings.numCopies;
}
} catch (e) {
dump("problems getting printingPromptService\n");
}
}
// ---------------------------------------------------
function doPrintRange(inx)
{
if (inx == 1) {
dialog.frompageInput.removeAttribute("disabled");
dialog.frompageLabel.removeAttribute("disabled");
dialog.topageInput.removeAttribute("disabled");
dialog.topageLabel.removeAttribute("disabled");
} else {
dialog.frompageInput.setAttribute("disabled", "true");
dialog.frompageLabel.setAttribute("disabled", "true");
dialog.topageInput.setAttribute("disabled", "true");
dialog.topageLabel.setAttribute("disabled", "true");
}
}
// ---------------------------------------------------
function loadDialog()
{
var print_copies = 1;
var print_selection_radio_enabled = false;
var print_frametype = gPrintSetInterface.kSelectedFrame;
var print_howToEnableUI = gPrintSetInterface.kFrameEnableNone;
var print_tofile = "";
try {
gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
printService = Components.classes["@mozilla.org/gfx/printsettings-service;1"];
if (printService) {
printService = printService.getService();
if (printService) {
printService = printService.QueryInterface(Components.interfaces.nsIPrintSettingsService);
}
}
} catch (e) {}
// Note: getPrinters sets up the PrintToFile control
getPrinters();
if (gPrintSettings) {
print_tofile = gPrintSettings.printToFile;
gOriginalNumCopies = gPrintSettings.numCopies;
print_copies = gPrintSettings.numCopies;
print_frametype = gPrintSettings.printFrameType;
print_howToEnableUI = gPrintSettings.howToEnableFrameUI;
print_selection_radio_enabled = gPrintSettings.GetPrintOptions(gPrintSetInterface.kEnableSelectionRB);
}
if (doDebug) {
dump("loadDialog*********************************************\n");
dump("print_tofile "+print_tofile+"\n");
dump("print_frame "+print_frametype+"\n");
dump("print_howToEnableUI "+print_howToEnableUI+"\n");
dump("selection_radio_enabled "+print_selection_radio_enabled+"\n");
}
dialog.printrangeGroup.selectedItem = dialog.allpagesRadio;
if (print_selection_radio_enabled) {
dialog.selectionRadio.removeAttribute("disabled");
} else {
dialog.selectionRadio.setAttribute("disabled", "true");
}
doPrintRange(dialog.rangeRadio.selected);
dialog.frompageInput.value = 1;
dialog.topageInput.value = 1;
dialog.numCopiesInput.value = print_copies;
if (doDebug) {
dump("print_howToEnableUI: "+print_howToEnableUI+"\n");
}
// print frame
if (print_howToEnableUI == gPrintSetInterface.kFrameEnableAll) {
dialog.aslaidoutRadio.removeAttribute("disabled");
dialog.selectedframeRadio.removeAttribute("disabled");
dialog.eachframesepRadio.removeAttribute("disabled");
dialog.printframeGroupLabel.removeAttribute("disabled");
// initialize radio group
dialog.printframeGroup.selectedItem = dialog.selectedframeRadio;
} else if (print_howToEnableUI == gPrintSetInterface.kFrameEnableAsIsAndEach) {
dialog.aslaidoutRadio.removeAttribute("disabled"); // enable
dialog.selectedframeRadio.setAttribute("disabled", "true"); // disable
dialog.eachframesepRadio.removeAttribute("disabled"); // enable
dialog.printframeGroupLabel.removeAttribute("disabled"); // enable
// initialize
dialog.printframeGroup.selectedItem = dialog.eachframesepRadio;
} else {
dialog.aslaidoutRadio.setAttribute("disabled", "true");
dialog.selectedframeRadio.setAttribute("disabled", "true");
dialog.eachframesepRadio.setAttribute("disabled", "true");
dialog.printframeGroupLabel.setAttribute("disabled", "true");
}
dialog.printButton.label = dialog.printName.getAttribute("label");
}
// ---------------------------------------------------
function onLoad()
{
// Init dialog.
initDialog();
// param[0]: nsIPrintSettings object
// param[1]: container for return value (1 = print, 0 = cancel)
gPrintSettings = window.arguments[0].QueryInterface(gPrintSetInterface);
gWebBrowserPrint = window.arguments[1].QueryInterface(Components.interfaces.nsIWebBrowserPrint);
paramBlock = window.arguments[2].QueryInterface(Components.interfaces.nsIDialogParamBlock);
// default return value is "cancel"
paramBlock.SetInt(0, 0);
loadDialog();
}
// ---------------------------------------------------
function onAccept()
{
if (gPrintSettings != null) {
var print_howToEnableUI = gPrintSetInterface.kFrameEnableNone;
// save these out so they can be picked up by the device spec
gPrintSettings.printerName = dialog.printerList.value;
print_howToEnableUI = gPrintSettings.howToEnableFrameUI;
gPrintSettings.printToFile = dialog.fileCheck.checked;
if (gPrintSettings.printToFile && !chooseFile())
return false;
if (dialog.allpagesRadio.selected) {
gPrintSettings.printRange = gPrintSetInterface.kRangeAllPages;
} else if (dialog.rangeRadio.selected) {
gPrintSettings.printRange = gPrintSetInterface.kRangeSpecifiedPageRange;
} else if (dialog.selectionRadio.selected) {
gPrintSettings.printRange = gPrintSetInterface.kRangeSelection;
}
gPrintSettings.startPageRange = dialog.frompageInput.value;
gPrintSettings.endPageRange = dialog.topageInput.value;
gPrintSettings.numCopies = dialog.numCopiesInput.value;
var frametype = gPrintSetInterface.kNoFrames;
if (print_howToEnableUI != gPrintSetInterface.kFrameEnableNone) {
if (dialog.aslaidoutRadio.selected) {
frametype = gPrintSetInterface.kFramesAsIs;
} else if (dialog.selectedframeRadio.selected) {
frametype = gPrintSetInterface.kSelectedFrame;
} else if (dialog.eachframesepRadio.selected) {
frametype = gPrintSetInterface.kEachFrameSep;
} else {
frametype = gPrintSetInterface.kSelectedFrame;
}
}
gPrintSettings.printFrameType = frametype;
if (doDebug) {
dump("onAccept*********************************************\n");
dump("frametype "+frametype+"\n");
dump("numCopies "+gPrintSettings.numCopies+"\n");
dump("printRange "+gPrintSettings.printRange+"\n");
dump("printerName "+gPrintSettings.printerName+"\n");
dump("startPageRange "+gPrintSettings.startPageRange+"\n");
dump("endPageRange "+gPrintSettings.endPageRange+"\n");
dump("printToFile "+gPrintSettings.printToFile+"\n");
}
}
var saveToPrefs = false;
saveToPrefs = gPrefs.getBoolPref("print.save_print_settings");
if (saveToPrefs && printService != null) {
var flags = gPrintSetInterface.kInitSavePaperSize |
gPrintSetInterface.kInitSaveEdges |
gPrintSetInterface.kInitSaveInColor |
gPrintSetInterface.kInitSaveShrinkToFit |
gPrintSetInterface.kInitSaveScaling;
printService.savePrintSettingsToPrefs(gPrintSettings, true, flags);
}
// set return value to "print"
if (paramBlock) {
paramBlock.SetInt(0, 1);
} else {
dump("*** FATAL ERROR: No paramBlock\n");
}
return true;
}
// ---------------------------------------------------
function onCancel()
{
// set return value to "cancel"
if (paramBlock) {
paramBlock.SetInt(0, 0);
} else {
dump("*** FATAL ERROR: No paramBlock\n");
}
return true;
}
// ---------------------------------------------------
const nsIFilePicker = Components.interfaces.nsIFilePicker;
function chooseFile()
{
try {
var fp = Components.classes["@mozilla.org/filepicker;1"]
.createInstance(nsIFilePicker);
fp.init(window, dialog.fpDialog.getAttribute("label"), nsIFilePicker.modeSave);
fp.appendFilters(nsIFilePicker.filterAll);
if (fp.show() != Components.interfaces.nsIFilePicker.returnCancel &&
fp.file && fp.file.path) {
gPrintSettings.toFileName = fp.file.path;
return true;
}
} catch (ex) {
dump(ex);
}
return false;
}

View file

@ -0,0 +1,126 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://global/locale/printdialog.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
ondialogaccept="return onAccept();"
oncancel="return onCancel();"
buttoniconaccept="print"
title="&printDialog.title;"
persist="screenX screenY"
screenX="24" screenY="24">
<script type="application/javascript" src="chrome://global/content/printdialog.js"/>
<stringbundle id="printingBundle" src="chrome://global/locale/printing.properties"/>
<groupbox>
<caption label="&printer.label;"/>
<grid>
<columns>
<column/>
<column flex="1"/>
<column/>
</columns>
<rows>
<row align="center">
<hbox align="center" pack="end">
<label id="printerLabel"
value="&printerInput.label;"
accesskey="&printerInput.accesskey;"
control="printerList"/>
</hbox>
<menulist id="printerList" flex="1" type="description" oncommand="setPrinterDefaultsForSelectedPrinter();"/>
<button id="properties"
label="&propertiesButton.label;"
accesskey="&propertiesButton.accesskey;"
icon="properties"
oncommand="displayPropertiesDialog();"/>
</row>
<row align="center">
<hbox align="center" pack="end">
<label id="descTextLabel" control="descText" value="&descText.label;"/>
</hbox>
<label id="descText"/>
<checkbox id="fileCheck"
checked="false"
label="&fileCheck.label;"
accesskey="&fileCheck.accesskey;"
pack="end"/>
</row>
</rows>
</grid>
</groupbox>
<hbox>
<groupbox flex="1">
<caption label="&printrangeGroup.label;"/>
<radiogroup id="printrangeGroup">
<radio id="allpagesRadio"
label="&allpagesRadio.label;"
accesskey="&allpagesRadio.accesskey;"
oncommand="doPrintRange(0)"/>
<hbox align="center">
<radio id="rangeRadio"
label="&rangeRadio.label;"
accesskey="&rangeRadio.accesskey;"
oncommand="doPrintRange(1)"/>
<label id="frompageLabel"
control="frompageInput"
value="&frompageInput.label;"
accesskey="&frompageInput.accesskey;"/>
<textbox id="frompageInput" style="width:5em;" onkeyup="checkInteger(this)"/>
<label id="topageLabel"
control="topageInput"
value="&topageInput.label;"
accesskey="&topageInput.accesskey;"/>
<textbox id="topageInput" style="width:5em;" onkeyup="checkInteger(this)"/>
</hbox>
<radio id="selectionRadio"
label="&selectionRadio.label;"
accesskey="&selectionRadio.accesskey;"
oncommand="doPrintRange(2)"/>
</radiogroup>
</groupbox>
<groupbox flex="1">
<caption label="&copies.label;"/>
<hbox align="center">
<label control="numCopiesInput"
value="&numCopies.label;"
accesskey="&numCopies.accesskey;"/>
<textbox id="numCopiesInput" style="width:5em;" onkeyup="checkInteger(this)"/>
</hbox>
</groupbox>
</hbox>
<groupbox flex="1">
<caption label="&printframeGroup.label;" id="printframeGroupLabel"/>
<radiogroup id="printframeGroup">
<radio id="aslaidoutRadio"
label="&aslaidoutRadio.label;"
accesskey="&aslaidoutRadio.accesskey;"/>
<radio id="selectedframeRadio"
label="&selectedframeRadio.label;"
accesskey="&selectedframeRadio.accesskey;"/>
<radio id="eachframesepRadio"
label="&eachframesepRadio.label;"
accesskey="&eachframesepRadio.accesskey;"/>
</radiogroup>
</groupbox>
<!-- used to store titles and labels -->
<data style="display:none;" id="printButton" label="&printButton.label;"/>
<data style="display:none;" id="fpDialog" label="&fpDialog.title;"/>
</dialog>

View file

@ -0,0 +1,401 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var dialog;
var gPrintBundle;
var gPrintSettings = null;
var gPrintSettingsInterface = Components.interfaces.nsIPrintSettings;
var gPaperArray;
var gPrefs;
var gPrintSetInterface = Components.interfaces.nsIPrintSettings;
var doDebug = true;
// ---------------------------------------------------
function checkDouble(element, maxVal)
{
var value = element.value;
if (value && value.length > 0) {
value = value.replace(/[^\.|^0-9]/g, "");
if (!value) {
element.value = "";
} else if (value > maxVal) {
element.value = maxVal;
} else {
element.value = value;
}
}
}
// ---------------------------------------------------
function isListOfPrinterFeaturesAvailable()
{
var has_printerfeatures = false;
try {
has_printerfeatures = gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".has_special_printerfeatures");
} catch (ex) {
}
return has_printerfeatures;
}
// ---------------------------------------------------
function getDoubleStr(val, dec)
{
var str = val.toString();
var inx = str.indexOf(".");
return str.substring(0, inx+dec+1);
}
// ---------------------------------------------------
function initDialog()
{
gPrintBundle = document.getElementById("printBundle");
dialog = {};
dialog.paperList = document.getElementById("paperList");
dialog.paperGroup = document.getElementById("paperGroup");
dialog.jobTitleLabel = document.getElementById("jobTitleLabel");
dialog.jobTitleGroup = document.getElementById("jobTitleGroup");
dialog.jobTitleInput = document.getElementById("jobTitleInput");
dialog.colorGroup = document.getElementById("colorGroup");
dialog.colorRadioGroup = document.getElementById("colorRadioGroup");
dialog.colorRadio = document.getElementById("colorRadio");
dialog.grayRadio = document.getElementById("grayRadio");
dialog.topInput = document.getElementById("topInput");
dialog.bottomInput = document.getElementById("bottomInput");
dialog.leftInput = document.getElementById("leftInput");
dialog.rightInput = document.getElementById("rightInput");
}
// ---------------------------------------------------
function round10(val)
{
return Math.round(val * 10) / 10;
}
// ---------------------------------------------------
function paperListElement(aPaperListElement)
{
this.paperListElement = aPaperListElement;
}
paperListElement.prototype =
{
clearPaperList:
function ()
{
// remove the menupopup node child of the menulist.
this.paperListElement.removeChild(this.paperListElement.firstChild);
},
appendPaperNames:
function (aDataObject)
{
var popupNode = document.createElement("menupopup");
for (var i=0;i<aDataObject.length;i++) {
var paperObj = aDataObject[i];
var itemNode = document.createElement("menuitem");
var label;
try {
label = gPrintBundle.getString(paperObj.name);
}
catch (e) {
/* No name in string bundle ? Then build one manually (this
* usually happens when gPaperArray was build by createPaperArrayFromPrinterFeatures() ...) */
if (paperObj.inches) {
label = paperObj.name + " (" + round10(paperObj.width) + "x" + round10(paperObj.height) + " inch)";
}
else {
label = paperObj.name + " (" + paperObj.width + "x" + paperObj.height + " mm)";
}
}
itemNode.setAttribute("label", label);
itemNode.setAttribute("value", i);
popupNode.appendChild(itemNode);
}
this.paperListElement.appendChild(popupNode);
}
};
// ---------------------------------------------------
function createPaperArrayFromDefaults()
{
var paperNames = ["letterSize", "legalSize", "exectiveSize", "a5Size", "a4Size", "a3Size", "a2Size", "a1Size", "a0Size"];
// var paperNames = ["&letterRadio.label;", "&legalRadio.label;", "&exectiveRadio.label;", "&a4Radio.label;", "&a3Radio.label;"];
var paperWidths = [ 8.5, 8.5, 7.25, 148.0, 210.0, 287.0, 420.0, 594.0, 841.0];
var paperHeights = [11.0, 14.0, 10.50, 210.0, 297.0, 420.0, 594.0, 841.0, 1189.0];
var paperInches = [true, true, true, false, false, false, false, false, false];
gPaperArray = new Array();
for (var i=0;i<paperNames.length;i++) {
var obj = {};
obj.name = paperNames[i];
obj.width = paperWidths[i];
obj.height = paperHeights[i];
obj.inches = paperInches[i];
/* Calculate the width/height in millimeters */
if (paperInches[i]) {
obj.width_mm = paperWidths[i] * 25.4;
obj.height_mm = paperHeights[i] * 25.4;
}
else {
obj.width_mm = paperWidths[i];
obj.height_mm = paperHeights[i];
}
gPaperArray[i] = obj;
}
}
// ---------------------------------------------------
function createPaperArrayFromPrinterFeatures()
{
var printername = gPrintSettings.printerName;
if (doDebug) {
dump("createPaperArrayFromPrinterFeatures for " + printername + ".\n");
}
gPaperArray = new Array();
var numPapers = gPrefs.getIntPref("print.tmp.printerfeatures." + printername + ".paper.count");
if (doDebug) {
dump("processing " + numPapers + " entries...\n");
}
for (var i=0;i<numPapers;i++) {
var obj = {};
obj.name = gPrefs.getCharPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".name");
obj.width_mm = gPrefs.getIntPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".width_mm");
obj.height_mm = gPrefs.getIntPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".height_mm");
obj.inches = gPrefs.getBoolPref("print.tmp.printerfeatures." + printername + ".paper." + i + ".is_inch");
/* Calculate the width/height in paper's native units (either inches or millimeters) */
if (obj.inches) {
obj.width = obj.width_mm / 25.4;
obj.height = obj.height_mm / 25.4;
}
else {
obj.width = obj.width_mm;
obj.height = obj.height_mm;
}
gPaperArray[i] = obj;
if (doDebug) {
dump("paper index=" + i + ", name=" + obj.name + ", width=" + obj.width + ", height=" + obj.height + ".\n");
}
}
}
// ---------------------------------------------------
function createPaperArray()
{
if (isListOfPrinterFeaturesAvailable()) {
createPaperArrayFromPrinterFeatures();
}
else {
createPaperArrayFromDefaults();
}
}
// ---------------------------------------------------
function createPaperSizeList(selectedInx)
{
var selectElement = new paperListElement(dialog.paperList);
selectElement.clearPaperList();
selectElement.appendPaperNames(gPaperArray);
if (selectedInx > -1) {
selectElement.paperListElement.selectedIndex = selectedInx;
}
// dialog.paperList = selectElement;
}
// ---------------------------------------------------
function loadDialog()
{
var print_paper_unit = 0;
var print_paper_width = 0.0;
var print_paper_height = 0.0;
var print_paper_name = "";
var print_color = true;
var print_jobtitle = "";
gPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
if (gPrintSettings) {
print_paper_unit = gPrintSettings.paperSizeUnit;
print_paper_width = gPrintSettings.paperWidth;
print_paper_height = gPrintSettings.paperHeight;
print_paper_name = gPrintSettings.paperName;
print_color = gPrintSettings.printInColor;
print_jobtitle = gPrintSettings.title;
}
if (doDebug) {
dump("loadDialog******************************\n");
dump("paperSizeType "+print_paper_unit+"\n");
dump("paperWidth "+print_paper_width+"\n");
dump("paperHeight "+print_paper_height+"\n");
dump("paperName "+print_paper_name+"\n");
dump("print_color "+print_color+"\n");
dump("print_jobtitle "+print_jobtitle+"\n");
}
createPaperArray();
var paperSelectedInx = 0;
for (var i=0;i<gPaperArray.length;i++) {
if (print_paper_name == gPaperArray[i].name) {
paperSelectedInx = i;
break;
}
}
if (doDebug) {
if (i == gPaperArray.length)
dump("loadDialog: No paper found.\n");
else
dump("loadDialog: found paper '"+gPaperArray[paperSelectedInx].name+"'.\n");
}
createPaperSizeList(paperSelectedInx);
/* Enable/disable and/or hide/unhide widgets based in the information
* whether the selected printer and/or print module supports the matching
* feature or not */
if (isListOfPrinterFeaturesAvailable()) {
// job title
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_jobtitle"))
dialog.jobTitleInput.removeAttribute("disabled");
else
dialog.jobTitleInput.setAttribute("disabled", "true");
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".supports_jobtitle_change"))
dialog.jobTitleGroup.removeAttribute("hidden");
else
dialog.jobTitleGroup.setAttribute("hidden", "true");
// paper size
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_paper_size"))
dialog.paperList.removeAttribute("disabled");
else
dialog.paperList.setAttribute("disabled", "true");
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".supports_paper_size_change"))
dialog.paperGroup.removeAttribute("hidden");
else
dialog.paperGroup.setAttribute("hidden", "true");
// color/grayscale radio
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".can_change_printincolor"))
dialog.colorRadioGroup.removeAttribute("disabled");
else
dialog.colorRadioGroup.setAttribute("disabled", "true");
if (gPrefs.getBoolPref("print.tmp.printerfeatures." + gPrintSettings.printerName + ".supports_printincolor_change"))
dialog.colorGroup.removeAttribute("hidden");
else
dialog.colorGroup.setAttribute("hidden", "true");
}
if (print_color) {
dialog.colorRadioGroup.selectedItem = dialog.colorRadio;
} else {
dialog.colorRadioGroup.selectedItem = dialog.grayRadio;
}
dialog.jobTitleInput.value = print_jobtitle;
dialog.topInput.value = gPrintSettings.edgeTop.toFixed(2);
dialog.bottomInput.value = gPrintSettings.edgeBottom.toFixed(2);
dialog.leftInput.value = gPrintSettings.edgeLeft.toFixed(2);
dialog.rightInput.value = gPrintSettings.edgeRight.toFixed(2);
}
// ---------------------------------------------------
function onLoad()
{
// Init dialog.
initDialog();
gPrintSettings = window.arguments[0].QueryInterface(gPrintSetInterface);
paramBlock = window.arguments[1].QueryInterface(Components.interfaces.nsIDialogParamBlock);
if (doDebug) {
if (gPrintSettings == null) alert("PrintSettings is null!");
if (paramBlock == null) alert("nsIDialogParam is null!");
}
// default return value is "cancel"
paramBlock.SetInt(0, 0);
loadDialog();
}
// ---------------------------------------------------
function onAccept()
{
var print_paper_unit = gPrintSettingsInterface.kPaperSizeInches;
var print_paper_width = 0.0;
var print_paper_height = 0.0;
var print_paper_name = "";
if (gPrintSettings != null) {
var paperSelectedInx = dialog.paperList.selectedIndex;
if (gPaperArray[paperSelectedInx].inches) {
print_paper_unit = gPrintSettingsInterface.kPaperSizeInches;
} else {
print_paper_unit = gPrintSettingsInterface.kPaperSizeMillimeters;
}
print_paper_width = gPaperArray[paperSelectedInx].width;
print_paper_height = gPaperArray[paperSelectedInx].height;
print_paper_name = gPaperArray[paperSelectedInx].name;
gPrintSettings.paperSizeUnit = print_paper_unit;
gPrintSettings.paperWidth = print_paper_width;
gPrintSettings.paperHeight = print_paper_height;
gPrintSettings.paperName = print_paper_name;
// save these out so they can be picked up by the device spec
gPrintSettings.printInColor = dialog.colorRadio.selected;
gPrintSettings.title = dialog.jobTitleInput.value;
gPrintSettings.edgeTop = dialog.topInput.value;
gPrintSettings.edgeBottom = dialog.bottomInput.value;
gPrintSettings.edgeLeft = dialog.leftInput.value;
gPrintSettings.edgeRight = dialog.rightInput.value;
if (doDebug) {
dump("onAccept******************************\n");
dump("paperSizeUnit "+print_paper_unit+"\n");
dump("paperWidth "+print_paper_width+"\n");
dump("paperHeight "+print_paper_height+"\n");
dump("paperName '"+print_paper_name+"'\n");
dump("printInColor "+gPrintSettings.printInColor+"\n");
}
} else {
dump("************ onAccept gPrintSettings: "+gPrintSettings+"\n");
}
if (paramBlock) {
// set return value to "ok"
paramBlock.SetInt(0, 1);
} else {
dump("*** FATAL ERROR: paramBlock missing\n");
}
return true;
}

View file

@ -0,0 +1,110 @@
<?xml version="1.0"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://global/locale/printjoboptions.dtd">
<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="onLoad();"
ondialogaccept="return onAccept();"
title="&printJobOptions.title;"
persist="screenX screenY"
screenX="24" screenY="24">
<script type="application/javascript" src="chrome://global/content/printjoboptions.js"/>
<stringbundle id="printBundle" src="chrome://global/locale/printPageSetup.properties"/>
<grid>
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row id="jobTitleGroup">
<hbox align="center" pack="end">
<label id="jobTitleLabel"
value="&jobTitleInput.label;"
accesskey="&jobTitleInput.accesskey;"
control="jobTitleInput"/>
</hbox>
<textbox id="jobTitleInput" flex="1"/>
</row>
<row id="paperGroup">
<hbox align="center" pack="end">
<label id="paperLabel"
value="&paperInput.label;"
accesskey="&paperInput.accesskey;"
control="paperList"/>
</hbox>
<menulist id="paperList" flex="1">
<menupopup/>
</menulist>
</row>
<row id="colorGroup">
<hbox align="center" pack="end">
<label control="colorRadioGroup" value="&colorGroup.label;"/>
</hbox>
<radiogroup id="colorRadioGroup" orient="horizontal">
<radio id="grayRadio"
label="&grayRadio.label;"
accesskey="&grayRadio.accesskey;"/>
<radio id="colorRadio"
label="&colorRadio.label;"
accesskey="&colorRadio.accesskey;"/>
</radiogroup>
</row>
</rows>
</grid>
<grid>
<columns>
<column/>
</columns>
<rows>
<row>
<groupbox flex="1">
<caption label="&edgeMarginInput.label;"/>
<hbox>
<hbox align="center">
<label id="topLabel"
value="&topInput.label;"
accesskey="&topInput.accesskey;"
control="topInput"/>
<textbox id="topInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
<hbox align="center">
<label id="bottomLabel"
value="&bottomInput.label;"
accesskey="&bottomInput.accesskey;"
control="bottomInput"/>
<textbox id="bottomInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
<hbox align="center">
<label id="leftLabel"
value="&leftInput.label;"
accesskey="&leftInput.accesskey;"
control="leftInput"/>
<textbox id="leftInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
<hbox align="center">
<label id="rightLabel"
value="&rightInput.label;"
accesskey="&rightInput.accesskey;"
control="rightInput"/>
<textbox id="rightInput" style="width:5em;" onkeyup="checkDouble(this, 0.5)"/>
</hbox>
</hbox>
</groupbox>
</row>
</rows>
</grid>
</dialog>

View file

@ -0,0 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* This file defines specific rules for print preview when using simplify mode.
* These rules already exist on aboutReaderControls.css, however, we decoupled it
* from the original file so we don't need to load a bunch of extra queries that
* will not take effect when using the simplify page checkbox. This file defines
* styling for title and author on the header element. */
.header > h1 {
font-size: 1.6em;
line-height: 1.25em;
margin: 30px 0;
}
.header > .credits {
font-size: 0.9em;
line-height: 1.48em;
margin: 0 0 30px 0;
font-style: italic;
}