From 82ca67dee0b0b33c13200f381f27f50fb048d9e3 Mon Sep 17 00:00:00 2001 From: Sam Foster Date: Tue, 21 Jul 2020 10:31:10 +0000 Subject: [PATCH] Bug 1652861 - Rough in UI for printer selection and print settings. r=mstriemer,fluent-reviewers,flod * New printUI strings * First pass at layout styling * Minimal controller and view code - UI components are templated and rendered but not populated by print/printer data - No view logic or user interaction handling Differential Revision: https://phabricator.services.mozilla.com/D83603 --- toolkit/components/printing/content/print.css | 98 +++++++++ .../components/printing/content/print.html | 100 ++++++++- toolkit/components/printing/content/print.js | 199 +++++++++++++++++- .../en-US/toolkit/printing/printUI.ftl | 46 ++++ 4 files changed, 432 insertions(+), 11 deletions(-) create mode 100644 toolkit/locales/en-US/toolkit/printing/printUI.ftl diff --git a/toolkit/components/printing/content/print.css b/toolkit/components/printing/content/print.css index e0032240a4d2..8608cec7aa0d 100644 --- a/toolkit/components/printing/content/print.css +++ b/toolkit/components/printing/content/print.css @@ -1,3 +1,101 @@ /* 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/. */ + +html, body { + height: 100%; +} + +body { + display: flex; + flex-direction: column; + justify-content: flex-start; + overflow: hidden; +} + +.row { + padding-inline-start: 34px; + margin-block: 18px; +} + +.row .block-label { + display: block; + margin-bottom: 4px; +} +.row .block-label + input, +.row .block-label + select, +.row .block-label + .page-range-input select { + margin-inline-start: 0; +} + +.header-container { + display: flex; + flex-direction: row; + flex: 0 1 auto; + border-bottom: 1px solid var(--in-content-border-color); + margin-block: 18px 0; +} +.header-container > h2 { + margin-top: 0; +} +.header-container > #sheets-count { + display: none; +} + +form#print { + display: flex; + flex: 1 1 auto; + flex-direction: column; + justify-content: flex-start; + overflow: hidden; +} + +.body-container { + flex: 1 1 auto; + overflow: auto; +} + +#more-settings { + border-top: 1px solid var(--in-content-border-color); +} + +#more-settings.twisty > summary { + list-style: none; + display: flex; + cursor: pointer; + padding-inline-end: 8px; +} + +#more-settings > summary > .twisty { + background-image: url("chrome://global/skin/icons/twisty-expanded.svg"); + background-repeat: no-repeat; + background-position: center; + width: 20px; + scale: 1 1; +} + +#more-settings > summary > .label { + flex-grow: 1; +} + +#more-settings[open] > summary > .twisty { + /* flip arrow to point up for the open state */ + scale: 1 -1; +} + +#open-dialog-link { + display: block; +} + +.footer-container { + border-top: 1px solid var(--in-content-border-color); + flex: 0 1 auto; +} + +#button-container > button:first-child { + margin-inline-start: 0; +} + +.page-range-input:not(.custom-input-selected) #custom-range { + display: none; +} diff --git a/toolkit/components/printing/content/print.html b/toolkit/components/printing/content/print.html index 7e12c641cfb0..b50086fcbe00 100644 --- a/toolkit/components/printing/content/print.html +++ b/toolkit/components/printing/content/print.html @@ -4,14 +4,106 @@ - You can obtain one at http://mozilla.org/MPL/2.0/. --> - + + + + + + + -

Print

-

- Open Native Dialog... + + + + + + + + +
+

+

+
+ +
+
+
+ + +
+
+
+ + +
+ +
+
+ + +
+
+ +
+ + +
+ +
+ +
+ +
+
+
+
+
+ + +
diff --git a/toolkit/components/printing/content/print.js b/toolkit/components/printing/content/print.js index e598e64b2df0..7c35c7123f11 100644 --- a/toolkit/components/printing/content/print.js +++ b/toolkit/components/printing/content/print.js @@ -4,12 +4,72 @@ const { gBrowser, PrintUtils } = window.docShell.chromeEventHandler.ownerGlobal; -function initialize(sourceBrowser) { - document.getElementById("tab-title").textContent = sourceBrowser.contentTitle; - document.getElementById("open-dialog-link").addEventListener("click", e => { - PrintUtils.printWindow(sourceBrowser.browsingContext); - }); -} +const PrintUI = { + initialize(sourceBrowser) { + this.sourceBrowser = sourceBrowser; + + this.form = document.querySelector("form#print"); + this._openDialogLink = document.querySelector("#open-dialog-link"); + this._settingsSection = document.querySelector("#settings"); + this._printerPicker = document.querySelector("#printer-picker"); + this._sheetsCount = document.querySelector("#sheets-count"); + + this.form.addEventListener("submit", this); + this._openDialogLink.addEventListener("click", event => { + event.preventDefault(); + PrintUtils.printWindow(sourceBrowser.browsingContext); + }); + this._printerPicker.addEventListener("change", this); + this._settingsSection.addEventListener("change", this); + + this.printDestinations = []; + this.printSettings = PrintUtils.getPrintSettings(); + // TODO: figure out where this data comes from + this.numSheets = 1; + + this.render(); + }, + + render() { + console.log( + "TODO: populate the UI with printer listing with printDestinations:", + this.printDestinations + ); + // TODO: populate the settings controls with an nsIPrintSettings + + document.l10n.setAttributes( + this._sheetsCount, + this._sheetsCount.getAttribute("data-deferred-l10n-id"), + { + sheetCount: this.numSheets, + } + ); + }, + + handleEvent(event) { + if (event.type == "submit" && event.target == this.form) { + event.preventDefault(); + switch (event.submitter.name) { + case "print": + PrintUtils.printWindow(this.sourceBrowser.browsingContext, { + printSilent: true, + printerName: this._printerPicker.value, + }); + break; + case "cancel": + console.log( + "TODO: trigger any teardown, exit the print preview and close the tab-modal" + ); + break; + } + } + /* TODO: + * handle clicks to the system dialog link + * handle change of the selected printer/destination + * handle changes from each of the print settings controls + */ + }, +}; function getSourceBrowser() { let params = new URLSearchParams(location.search); @@ -27,8 +87,133 @@ function getSourceBrowser() { document.addEventListener("DOMContentLoaded", e => { let sourceBrowser = getSourceBrowser(); if (sourceBrowser) { - initialize(sourceBrowser); + PrintUI.initialize(sourceBrowser); } else { console.error("No source browser"); } }); + +/* + * Custom elements ---------------------------------------------------- + */ + +function PrintUIControlMixin(superClass) { + return class PrintUIControl extends superClass { + connectedCallback() { + this.initialize(); + this.render(); + } + initialize() { + if (this._initialized) { + return; + } + this._initialized = true; + if (this.templateId) { + let template = this.ownerDocument.getElementById(this.templateId); + let templateContent = template.content; + this.appendChild(templateContent.cloneNode(true)); + } + } + render() {} + }; +} + +class DestinationPicker extends HTMLSelectElement { + setOptions(optionValues = []) { + console.log("DestinationPicker, setOptions:", optionValues); + this.textContent = ""; + for (let optionData of optionValues) { + let opt = new Option( + optionData.name, + "value" in optionData ? optionData.value : optionData.name + ); + if (optionData.selected) { + opt.selected = true; + } + this.options.add(opt); + } + } +} +customElements.define("destination-picker", DestinationPicker, { + extends: "select", +}); + +class OrientationInput extends PrintUIControlMixin(HTMLElement) { + get templateId() { + return "orientation-template"; + } + + constructor() { + super(); + this._orientation = null; + } + + render() { + console.log( + "TODO: populate/set orientation state from the current print settings" + ); + } +} +customElements.define("orientation-input", OrientationInput); + +class ScaleInput extends PrintUIControlMixin(HTMLElement) { + get templateId() { + return "scale-template"; + } + + render() { + console.log( + "TODO: populate/set print scale state from the current print settings" + ); + } +} +customElements.define("scale-input", ScaleInput); + +class PageRangeInput extends PrintUIControlMixin(HTMLElement) { + get templateId() { + return "page-range-template"; + } + + render() { + console.log( + "TODO: populate/set page-range state from the current print settings" + ); + } +} +customElements.define("page-range-input", PageRangeInput); + +class TwistySummary extends PrintUIControlMixin(HTMLElement) { + get isOpen() { + return this.closest("details")?.hasAttribute("open"); + } + + get templateId() { + return "twisty-summary-template"; + } + + initialize() { + if (this._initialized) { + return; + } + super.initialize(); + this.label = this.querySelector(".label"); + + this.addEventListener("click", this); + this.updateSummary(); + } + + handleEvent(event) { + let willOpen = !this.isOpen; + this.updateSummary(willOpen); + } + + updateSummary(open = false) { + document.l10n.setAttributes( + this.label, + open + ? this.getAttribute("data-open-l10n-id") + : this.getAttribute("data-closed-l10n-id") + ); + } +} +customElements.define("twisty-summary", TwistySummary); diff --git a/toolkit/locales/en-US/toolkit/printing/printUI.ftl b/toolkit/locales/en-US/toolkit/printing/printUI.ftl new file mode 100644 index 000000000000..31a532067940 --- /dev/null +++ b/toolkit/locales/en-US/toolkit/printing/printUI.ftl @@ -0,0 +1,46 @@ +# 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/. + +printui-title = Print + +# Variables +# $sheetCount (integer) - Number of paper sheets +printui-sheets-count = + { $sheetCount -> + [one] { $sheetCount } sheet of paper + *[other] { $sheetCount } sheets of paper + } + +printui-page-range-all = All +printui-page-range-custom = Custom +printui-page-range-label = Pages +printui-page-range-picker = + .aria-label = Pick page range +printui-page-custom-range = + .aria-label = Enter custom page range + +# Section title for the number of copies to print +printui-copies-label = Copies + +printui-orientation = Orientation +printui-landscape = Landscape +printui-portrait = Portrait + +# Section title for the printer or destination device to target +printui-destination-label = Destination + +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 + +printui-system-dialog-link = Print using the system dialog… + +printui-primary-button = Print +printui-cancel-button = Cancel +