зеркало из 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
|
||||
* 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;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,106 @@
|
|||
- You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
<html>
|
||||
<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/content/print.css">
|
||||
<script defer src="chrome://global/content/print.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Print</h1>
|
||||
<h2 id="tab-title"></h2>
|
||||
<a href="#" id="open-dialog-link">Open Native Dialog...</a>
|
||||
<template id="page-range-template">
|
||||
<select id="range-picker" name="page-range-type" data-l10n-id="printui-page-range-picker">
|
||||
<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>
|
||||
</html>
|
||||
|
|
|
@ -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 => {
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
Загрузка…
Ссылка в новой задаче