зеркало из https://github.com/mozilla/gecko-dev.git
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
This commit is contained in:
Родитель
4a597e3019
Коммит
82ca67dee0
|
@ -1,3 +1,101 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* 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
|
* 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/. */
|
* 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;
|
||||||
|
}
|
||||||
|
|
|
@ -4,14 +4,106 @@
|
||||||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href="chrome://global/content/print.css">
|
<meta charset="utf-8">
|
||||||
|
<title data-l10n-id="printui-title"></title>
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src chrome:;img-src data:; object-src 'none'">
|
||||||
|
|
||||||
|
<link rel="localization" href="toolkit/printing/printUI.ftl">
|
||||||
|
|
||||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
||||||
|
<link rel="stylesheet" href="chrome://global/content/print.css">
|
||||||
<script defer src="chrome://global/content/print.js"></script>
|
<script defer src="chrome://global/content/print.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>Print</h1>
|
<template id="page-range-template">
|
||||||
<h2 id="tab-title"></h2>
|
<select id="range-picker" name="page-range-type" data-l10n-id="printui-page-range-picker">
|
||||||
<a href="#" id="open-dialog-link">Open Native Dialog...</a>
|
<option value="all" selected data-l10n-id="printui-page-range-all"></option>
|
||||||
|
<option value="custom" data-l10n-id="printui-page-range-custom"></option>
|
||||||
|
</select>
|
||||||
|
<input id="custom-range" name="page-range" pattern="\d(-\d)?" type="text" hidden data-l10n-id="printui-page-custom-range">
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="orientation-template">
|
||||||
|
<span>
|
||||||
|
<input type="radio" name="orientation" id="portrait" value="0" checked>
|
||||||
|
<label for="portrait" data-l10n-id="printui-portrait"></label>
|
||||||
|
</span>
|
||||||
|
<span>
|
||||||
|
<input type="radio" name="orientation" id="landscape" value="1">
|
||||||
|
<label for="landscape" data-l10n-id="printui-landscape"></label>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="twisty-summary-template">
|
||||||
|
<span class="label"></span>
|
||||||
|
<span class="twisty"></span>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template id="scale-template">
|
||||||
|
<div role="radiogroup" aria-labelledby="scale-label">
|
||||||
|
<div>
|
||||||
|
<input type="radio" name="scale-choice" id="fit-choice" value="fit" checked>
|
||||||
|
<label for="fit-choice" data-l10n-id="printui-scale-fit-to-page"></label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="radio" name="scale-choice" id="percent-scale-choice">
|
||||||
|
<label for="percent-scale-choice" data-l10n-id="printui-scale-pcent"></label>
|
||||||
|
<input id="percent-scale" type="text" placeholder="100%" disabled>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<header class="row header-container">
|
||||||
|
<h2 data-l10n-id="printui-title"></h2>
|
||||||
|
<p id="sheets-count" data-deferred-l10n-id="printui-sheets-count"></p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form id="print">
|
||||||
|
<section class="body-container">
|
||||||
|
<section id="destination" class="row">
|
||||||
|
<label for="printer-picker" class="block-label" data-l10n-id="printui-destination-label"></label>
|
||||||
|
<select is="destination-picker" id="printer-picker"></select>
|
||||||
|
</section>
|
||||||
|
<section id="settings">
|
||||||
|
<section id="copies" class="row">
|
||||||
|
<label for="copies-count" class="block-label" data-l10n-id="printui-copies-label"></label>
|
||||||
|
<input id="copies-count" type="number" min="1">
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="orientation" class="row">
|
||||||
|
<div role="radiogroup" aria-labelledby="orientation-label">
|
||||||
|
<label class="block-label" data-l10n-id="printui-orientation"></label>
|
||||||
|
<span id="orientation-input" is="orientation-input" class="orientation-input"></span>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="pages" class="row">
|
||||||
|
<label for="page-range-input" class="block-label" data-l10n-id="printui-page-range-label"></label>
|
||||||
|
<span id="page-range-input" is="page-range-input" class="page-range-input"></span>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
</details>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<footer class="footer-container">
|
||||||
|
<section id="system-print" class="row">
|
||||||
|
<a href="#" id="open-dialog-link" data-l10n-id="printui-system-dialog-link"></a>
|
||||||
|
</section>
|
||||||
|
<section id="button-container" class="row">
|
||||||
|
<button class="primary" name="print" data-l10n-id="printui-primary-button"></button>
|
||||||
|
<button name="cancel" data-l10n-id="printui-cancel-button"></button>
|
||||||
|
</section>
|
||||||
|
</footer>
|
||||||
|
</form>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -4,12 +4,72 @@
|
||||||
|
|
||||||
const { gBrowser, PrintUtils } = window.docShell.chromeEventHandler.ownerGlobal;
|
const { gBrowser, PrintUtils } = window.docShell.chromeEventHandler.ownerGlobal;
|
||||||
|
|
||||||
function initialize(sourceBrowser) {
|
const PrintUI = {
|
||||||
document.getElementById("tab-title").textContent = sourceBrowser.contentTitle;
|
initialize(sourceBrowser) {
|
||||||
document.getElementById("open-dialog-link").addEventListener("click", e => {
|
this.sourceBrowser = sourceBrowser;
|
||||||
PrintUtils.printWindow(sourceBrowser.browsingContext);
|
|
||||||
});
|
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() {
|
function getSourceBrowser() {
|
||||||
let params = new URLSearchParams(location.search);
|
let params = new URLSearchParams(location.search);
|
||||||
|
@ -27,8 +87,133 @@ function getSourceBrowser() {
|
||||||
document.addEventListener("DOMContentLoaded", e => {
|
document.addEventListener("DOMContentLoaded", e => {
|
||||||
let sourceBrowser = getSourceBrowser();
|
let sourceBrowser = getSourceBrowser();
|
||||||
if (sourceBrowser) {
|
if (sourceBrowser) {
|
||||||
initialize(sourceBrowser);
|
PrintUI.initialize(sourceBrowser);
|
||||||
} else {
|
} else {
|
||||||
console.error("No source browser");
|
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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче