Bug 1654073 - Add options section with background and header/footer controls. r=mstriemer,fluent-reviewers,flod
authorSam Foster <sfoster@mozilla.com>
Mon, 03 Aug 2020 06:20:53 +0000
changeset 543054 a25524d613da49b37f0b8e2d19bd38ebaa6af1e5
parent 543053 092c2125463531e3bd8f095457df7440b1e8fe99
child 543055 28f5bc0faffe5c2c6db2a67980240c50b1d1fc8f
push id37664
push userncsoregi@mozilla.com
push dateMon, 03 Aug 2020 21:39:27 +0000
treeherdermozilla-central@255b4f5888e9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstriemer, fluent-reviewers, flod
bugs1654073
milestone81.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1654073 - Add options section with background and header/footer controls. r=mstriemer,fluent-reviewers,flod * Pass a proxy to the settings object to the UI components * Components can pass multiple changed settings Differential Revision: https://phabricator.services.mozilla.com/D84630
toolkit/components/printing/content/print.html
toolkit/components/printing/content/print.js
toolkit/locales/en-US/toolkit/printing/printUI.ftl
--- a/toolkit/components/printing/content/print.html
+++ b/toolkit/components/printing/content/print.html
@@ -86,16 +86,29 @@
           <details id="more-settings" class="twisty">
             <summary class="block-label row" is="twisty-summary"
                      data-open-l10n-id="printui-less-settings"
                      data-closed-l10n-id="printui-more-settings"></summary>
             <section id="scale" class="row">
               <label for="scale-control" class="block-label" data-l10n-id="printui-scale"></label>
               <div is="scale-input" id="scale-control" role="radiogroup"></div>
             </section>
+
+            <section id="more-settings-options" class="row">
+              <label class="block-label" data-l10n-id="printui-options"></label>
+              <div>
+                <input type="checkbox" id="headers-footers-enabled" disabled="">
+                <label for="headers-footers-enabled" data-l10n-id="printui-headers-footers-checkbox"></label>
+              </div>
+              <div>
+                <input is="backgrounds-input" type="checkbox" id="backgrounds-enabled">
+                <label for="backgrounds-enabled" data-l10n-id="printui-backgrounds-checkbox"></label>
+              </div>
+            </section>
+
           </details>
         </section>
       </section>
 
       <footer class="footer-container" id="print-footer">
         <section id="system-print" class="row">
           <a href="#" id="open-dialog-link" data-l10n-id="printui-system-dialog-link"></a>
         </section>
--- a/toolkit/components/printing/content/print.js
+++ b/toolkit/components/printing/content/print.js
@@ -22,47 +22,73 @@ window.addEventListener(
 
 var PrintEventHandler = {
   init() {
     this.sourceBrowser = this.getSourceBrowser();
     this.settings = PrintUtils.getPrintSettings();
     this.updatePrintPreview();
 
     document.addEventListener("print", e => this.print({ silent: true }));
-    document.addEventListener("update-print-setting", e =>
-      this.updateSetting(e.detail)
+    document.addEventListener("update-print-settings", e =>
+      this.updateSettings(e.detail)
     );
     document.addEventListener("cancel-print", () => this.cancelPrint());
     document.addEventListener("open-system-dialog", () =>
       this.print({ silent: false })
     );
     document.dispatchEvent(
       new CustomEvent("available-destinations", {
         detail: this.getPrintDestinations(),
       })
     );
 
-    this.settingValues = {
-      printRange: printRange =>
-        printRange == "all"
-          ? Ci.nsIPrintSettings.kRangeAllPages
-          : Ci.nsIPrintSettings.kRangeSpecifiedPageRange,
-      // TODO: There's also kRangeSelection, which should come into play
-      // once we have a text box where the user can specify a range
-    };
+    // Some settings are only used by the UI
+    // assigning new values should update the underlying settings
+    this.viewSettings = new Proxy(this.settings, {
+      get(target, name) {
+        switch (name) {
+          case "printBackgrounds":
+            return target.printBGImages || target.printBGColors;
+          case "printAllOrCustomRange":
+            return target.printRange == Ci.nsIPrintSettings.kRangeAllPages
+              ? "all"
+              : "custom";
+        }
+        return target[name];
+      },
+      set(target, name, value) {
+        switch (name) {
+          case "printBackgrounds":
+            target.printBGImages = value;
+            target.printBGColors = value;
+            break;
+          case "printAllOrCustomRange":
+            target.printRange =
+              value == "all"
+                ? Ci.nsIPrintSettings.kRangeAllPages
+                : Ci.nsIPrintSettings.kRangeSpecifiedPageRange;
+            // TODO: There's also kRangeSelection, which should come into play
+            // once we have a text box where the user can specify a range
+            break;
+          default:
+            target[name] = value;
+        }
+      },
+    });
+
     this.settingFlags = {
       orientation: Ci.nsIPrintSettings.kInitSaveOrientation,
       printerName: Ci.nsIPrintSettings.kInitSaveAll,
       scaling: Ci.nsIPrintSettings.kInitSaveScaling,
       shrinkToFit: Ci.nsIPrintSettings.kInitSaveShrinkToFit,
     };
 
     document.dispatchEvent(
       new CustomEvent("print-settings", {
-        detail: this.settings,
+        detail: this.viewSettings,
       })
     );
   },
 
   print({ printerName, silent } = {}) {
     let settings = this.settings;
     if (silent) {
       settings.printSilent = true;
@@ -72,39 +98,44 @@ var PrintEventHandler = {
     }
     PrintUtils.printWindow(this.sourceBrowser.browsingContext, settings);
   },
 
   cancelPrint() {
     window.close();
   },
 
-  updateSetting({ setting, value }) {
-    let settingValue =
-      setting in this.settingValues
-        ? this.settingValues[setting](value)
-        : value;
+  updateSettings(changedSettings = {}) {
+    let isChanged = false;
+    let flags = 0;
+    for (let [setting, value] of Object.entries(changedSettings)) {
+      if (this.viewSettings[setting] != value) {
+        this.viewSettings[setting] = value;
 
-    if (this.settings[setting] != settingValue) {
-      this.settings[setting] = settingValue;
+        if (setting in this.settingFlags) {
+          flags |= this.settingFlags[setting];
+        }
+        isChanged = true;
+      }
+    }
 
+    if (isChanged) {
       let PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].getService(
         Ci.nsIPrintSettingsService
       );
 
-      let flag = this.settingFlags[setting];
-      if (flag) {
-        PSSVC.savePrintSettingsToPrefs(this.settings, true, flag);
+      if (flags) {
+        PSSVC.savePrintSettingsToPrefs(this.settings, true, flags);
       }
 
       this.updatePrintPreview();
 
       document.dispatchEvent(
         new CustomEvent("print-settings", {
-          detail: this.settings,
+          detail: this.viewSettings,
         })
       );
     }
   },
 
   async updatePrintPreview() {
     if (this._previewUpdatingPromise) {
       if (!this._queuedPreviewUpdatePromise) {
@@ -194,32 +225,31 @@ function PrintUIControlMixin(superClass)
 
       this.addEventListener("change", this);
     }
 
     render() {}
 
     update(settings) {}
 
-    updateSetting(setting, value) {
+    dispatchSettingsChange(changedSettings) {
       this.dispatchEvent(
-        new CustomEvent("update-print-setting", {
+        new CustomEvent("update-print-settings", {
           bubbles: true,
-          detail: { setting, value },
+          detail: changedSettings,
         })
       );
     }
 
     handleEvent(event) {}
   };
 }
 
-class DestinationPicker extends HTMLSelectElement {
-  constructor() {
-    super();
+class DestinationPicker extends PrintUIControlMixin(HTMLSelectElement) {
+  initialize() {
     this.addEventListener("change", this);
     document.addEventListener("available-destinations", this);
   }
 
   setOptions(optionValues = []) {
     this._options = optionValues;
     this.textContent = "";
     for (let optionData of this._options) {
@@ -233,25 +263,19 @@ class DestinationPicker extends HTMLSele
       }
       this.options.add(opt);
     }
   }
 
   handleEvent(e) {
     if (e.type == "change") {
       this._currentPrinter = e.target.value;
-      this.dispatchEvent(
-        new CustomEvent("update-print-setting", {
-          bubbles: true,
-          detail: {
-            setting: "printerName",
-            value: e.target.value,
-          },
-        })
-      );
+      this.dispatchSettingsChange({
+        printerName: e.target.value,
+      });
     }
 
     if (e.type == "available-destinations") {
       this.setOptions(e.detail);
     }
   }
 }
 customElements.define("destination-picker", DestinationPicker, {
@@ -265,32 +289,36 @@ class OrientationInput extends PrintUICo
 
   update(settings) {
     for (let input of this.querySelectorAll("input")) {
       input.checked = settings.orientation == input.value;
     }
   }
 
   handleEvent(e) {
-    this.updateSetting("orientation", e.target.value);
+    this.dispatchSettingsChange({
+      orientation: e.target.value,
+    });
   }
 }
 customElements.define("orientation-input", OrientationInput);
 
 class CopiesInput extends PrintUIControlMixin(HTMLElement) {
   get templateId() {
     return "copy-count-template";
   }
 
   update(settings) {
     this.querySelector("input").value = settings.numCopies;
   }
 
   handleEvent(e) {
-    this.updateSetting("numCopies", e.target.value);
+    this.dispatchSettingsChange({
+      numCopies: e.target.value,
+    });
   }
 }
 customElements.define("copy-count-input", CopiesInput);
 
 class PrintUIForm extends PrintUIControlMixin(HTMLElement) {
   initialize() {
     super.initialize();
 
@@ -320,55 +348,80 @@ customElements.define("print-form", Prin
 
 class ScaleInput extends PrintUIControlMixin(HTMLElement) {
   get templateId() {
     return "scale-template";
   }
 
   initialize() {
     super.initialize();
-    this.addEventListener("input", this);
     this._percentScale = this.querySelector("#percent-scale");
+    this._percentScale.addEventListener("input", this);
     this._shrinkToFit = this.querySelector("#fit-choice");
   }
 
   update(settings) {
     // TODO: .scaling only goes from 0-1. Need validation mechanism
     let { scaling, shrinkToFit } = settings;
     this._shrinkToFit.checked = shrinkToFit;
     this.querySelector("#percent-scale-choice").checked = !shrinkToFit;
     this._percentScale.disabled = shrinkToFit;
 
     // Only allow whole numbers. 0.14 * 100 would have decimal places, etc.
     this._percentScale.value = parseInt(scaling * 100, 10);
   }
 
   handleEvent(e) {
-    this.updateSetting("shrinkToFit", this._shrinkToFit.checked);
-    this.updateSetting("scaling", this._percentScale.value / 100);
+    e.stopPropagation();
+    this.dispatchSettingsChange({
+      shrinkToFit: this._shrinkToFit.checked,
+      scaling: this._percentScale.value / 100,
+    });
   }
 }
 customElements.define("scale-input", ScaleInput);
 
 class PageRangeInput extends PrintUIControlMixin(HTMLElement) {
   get templateId() {
     return "page-range-template";
   }
 
   update(settings) {
-    let rangePicker = document.querySelector("#range-picker");
-    rangePicker.value = settings.printRange == 0 ? "all" : "custom";
+    let rangePicker = this.querySelector("#range-picker");
+    rangePicker.value = settings.printAllOrCustomRange;
   }
 
   handleEvent(e) {
-    this.updateSetting("printRange", e.target.value);
+    this.dispatchSettingsChange({
+      printAllOrCustomRange: e.target.value,
+    });
   }
 }
 customElements.define("page-range-input", PageRangeInput);
 
+class BackgroundsInput extends PrintUIControlMixin(HTMLInputElement) {
+  connectedCallback() {
+    this.type = "checkbox";
+    super.connectedCallback();
+  }
+
+  update(settings) {
+    this.checked = settings.printBackgrounds;
+  }
+
+  handleEvent(e) {
+    this.dispatchSettingsChange({
+      printBackgrounds: this.checked,
+    });
+  }
+}
+customElements.define("backgrounds-input", BackgroundsInput, {
+  extends: "input",
+});
+
 class TwistySummary extends PrintUIControlMixin(HTMLElement) {
   get isOpen() {
     return this.closest("details")?.hasAttribute("open");
   }
 
   get templateId() {
     return "twisty-summary-template";
   }
--- a/toolkit/locales/en-US/toolkit/printing/printUI.ftl
+++ b/toolkit/locales/en-US/toolkit/printing/printUI.ftl
@@ -34,13 +34,18 @@ printui-more-settings = More settings
 printui-less-settings = Fewer settings
 
 # Section title (noun) for the print scaling options
 printui-scale = Scale
 printui-scale-fit-to-page = Fit to page
 # Label for input control where user can set the scale percentage
 printui-scale-pcent = Scale
 
+# Section title for miscellaneous print options
+printui-options = Options
+printui-headers-footers-checkbox = Print headers and footers
+printui-backgrounds-checkbox = Print backgrounds
+
 printui-system-dialog-link = Print using the system dialog…
 
 printui-primary-button = Print
 printui-cancel-button = Cancel