Bug 1682162 - Use the paperSizeUnit to display and handle mm/inch custom margin values. r=emalysz,fluent-reviewers,flod

Differential Revision: https://phabricator.services.mozilla.com/D104291
This commit is contained in:
Sam Foster 2021-03-13 00:27:53 +00:00
parent 2dd2d5d19d
commit 72d4c476b1
6 changed files with 279 additions and 31 deletions

View File

@ -75,7 +75,7 @@
<option value="default" data-l10n-id="printui-margins-default"></option>
<option value="minimum" data-l10n-id="printui-margins-min"></option>
<option value="none" data-l10n-id="printui-margins-none"></option>
<option value="custom" data-l10n-id="printui-margins-custom-inches"></option>
<option value="custom" data-unit-prefix-l10n-id="printui-margins-custom-"></option>
</select>
<div id="custom-margins" class="margin-group" role="group" hidden>
<div class="vertical-margins">
@ -85,7 +85,7 @@
aria-describedby="margins-custom-margin-top-desc"
min="0" step="0.01" required>
<label for="custom-margin-top" class="margin-descriptor" data-l10n-id="printui-margins-custom-top"></label>
<label hidden id="margins-custom-margin-top-desc" data-l10n-id="printui-margins-custom-top-inches"></label>
<label hidden id="margins-custom-margin-top-desc" data-unit-prefix-l10n-id="printui-margins-custom-top-"></label>
</div>
<div class="margin-pair">
<input is="setting-number"
@ -93,7 +93,7 @@
aria-describedby="margins-custom-margin-bottom-desc"
min="0" step="0.01" required>
<label for="custom-margin-bottom" class="margin-descriptor" data-l10n-id="printui-margins-custom-bottom"></label>
<label hidden id="margins-custom-margin-bottom-desc" data-l10n-id="printui-margins-custom-bottom-inches"></label>
<label hidden id="margins-custom-margin-bottom-desc" data-unit-prefix-l10n-id="printui-margins-custom-bottom-"></label>
</div>
</div>
<div class="horizontal-margins">
@ -103,7 +103,7 @@
aria-describedby="margins-custom-margin-left-desc"
min="0" step="0.01" required>
<label for="custom-margin-left" class="margin-descriptor" data-l10n-id="printui-margins-custom-left"></label>
<label hidden id="margins-custom-margin-left-desc" data-l10n-id="printui-margins-custom-left-inches"></label>
<label hidden id="margins-custom-margin-left-desc" data-unit-prefix-l10n-id="printui-margins-custom-left-"></label>
</div>
<div class="margin-pair">
<input is="setting-number"
@ -111,7 +111,7 @@
aria-describedby="margins-custom-margin-right-desc"
min="0" step="0.01" required>
<label for="custom-margin-right" class="margin-descriptor" data-l10n-id="printui-margins-custom-right"></label>
<label hidden id="margins-custom-margin-right-desc" data-l10n-id="printui-margins-custom-right-inches"></label>
<label hidden id="margins-custom-margin-right-desc" data-unit-prefix-l10n-id="printui-margins-custom-right-"></label>
</div>
</div>
<p id="error-invalid-margin" hidden data-l10n-id="printui-error-invalid-margin" class="error-message" role="alert"></p>

View File

@ -24,6 +24,7 @@ const PDF_JS_URI = "resource://pdf.js/web/viewer.html";
const INPUT_DELAY_MS = Cu.isInAutomation ? 100 : 500;
const MM_PER_POINT = 25.4 / 72;
const INCHES_PER_POINT = 1 / 72;
const INCHES_PER_MM = 1 / 25.4;
const ourBrowser = window.docShell.chromeEventHandler;
const PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].getService(
Ci.nsIPrintSettingsService
@ -499,6 +500,10 @@ var PrintEventHandler = {
paperSizeUnit = PrintEventHandler.settings.kPaperSizeMillimeters;
} else {
paperId = this.viewSettings.paperId;
logger.debug(
"No paperId or matchedPaper, get a new default from viewSettings:",
paperId
);
paperWidth = this.viewSettings.paperWidth;
paperHeight = this.viewSettings.paperHeight;
paperSizeUnit = this.viewSettings.paperSizeUnit;
@ -2276,6 +2281,8 @@ class MarginsPicker extends PrintUIControlMixin(HTMLElement) {
this._customLeftMargin = this.querySelector("#custom-margin-left");
this._customRightMargin = this.querySelector("#custom-margin-right");
this._marginError = this.querySelector("#error-invalid-margin");
this._sizeUnit = null;
this._toInchesMultiplier = 1;
}
get templateId() {
@ -2284,10 +2291,10 @@ class MarginsPicker extends PrintUIControlMixin(HTMLElement) {
updateCustomMargins() {
let newMargins = {
marginTop: this._customTopMargin.value,
marginBottom: this._customBottomMargin.value,
marginLeft: this._customLeftMargin.value,
marginRight: this._customRightMargin.value,
marginTop: this.toInchValue(this._customTopMargin.value),
marginBottom: this.toInchValue(this._customBottomMargin.value),
marginLeft: this.toInchValue(this._customLeftMargin.value),
marginRight: this.toInchValue(this._customRightMargin.value),
};
this.dispatchSettingsChange({
@ -2298,12 +2305,12 @@ class MarginsPicker extends PrintUIControlMixin(HTMLElement) {
}
updateMaxValues() {
this._customTopMargin.max =
this._maxHeight - this._customBottomMargin.value;
this._customBottomMargin.max =
this._maxHeight - this._customTopMargin.value;
this._customLeftMargin.max = this._maxWidth - this._customRightMargin.value;
this._customRightMargin.max = this._maxWidth - this._customLeftMargin.value;
let maxWidth = this.toCurrentUnitValue(this._maxWidth);
let maxHeight = this.toCurrentUnitValue(this._maxHeight);
this._customTopMargin.max = maxHeight - this._customBottomMargin.value;
this._customBottomMargin.max = maxHeight - this._customTopMargin.value;
this._customLeftMargin.max = maxWidth - this._customRightMargin.value;
this._customRightMargin.max = maxWidth - this._customLeftMargin.value;
}
formatMargin(target) {
@ -2315,23 +2322,41 @@ class MarginsPicker extends PrintUIControlMixin(HTMLElement) {
}
}
toCurrentUnitValue(val) {
if (typeof val == "string") {
val = parseFloat(val);
}
return val / this._toInchesMultiplier;
}
toInchValue(val) {
if (typeof val == "string") {
val = parseFloat(val);
}
return val * this._toInchesMultiplier;
}
setAllMarginValues(settings) {
this._customTopMargin.value = parseFloat(
this._customTopMargin.value = this.toCurrentUnitValue(
settings.customMargins.marginTop
).toFixed(2);
this._customBottomMargin.value = parseFloat(
this._customBottomMargin.value = this.toCurrentUnitValue(
settings.customMargins.marginBottom
).toFixed(2);
this._customLeftMargin.value = parseFloat(
this._customLeftMargin.value = this.toCurrentUnitValue(
settings.customMargins.marginLeft
).toFixed(2);
this._customRightMargin.value = parseFloat(
this._customRightMargin.value = this.toCurrentUnitValue(
settings.customMargins.marginRight
).toFixed(2);
}
update(settings) {
// Re-evaluate which margin options should be enabled whenever the printer or paper changes
this._toInchesMultiplier =
settings.paperSizeUnit == settings.kPaperSizeMillimeters
? INCHES_PER_MM
: 1;
if (
settings.paperId !== this._paperId ||
settings.printerName !== this._printerName ||
@ -2345,17 +2370,23 @@ class MarginsPicker extends PrintUIControlMixin(HTMLElement) {
this._printerName = settings.printerName;
this._orientation = settings.orientation;
// Paper dimensions are in the paperSizeUnit. As the margin values are in inches
// we'll normalize to that when storing max dimensions
let height =
this._orientation == 0 ? settings.paperHeight : settings.paperWidth;
let width =
this._orientation == 0 ? settings.paperWidth : settings.paperHeight;
let heightInches =
Math.round(this._toInchesMultiplier * height * 100) / 100;
let widthInches =
Math.round(this._toInchesMultiplier * width * 100) / 100;
this._maxHeight =
height -
heightInches -
settings.unwriteableMarginTop -
settings.unwriteableMarginBottom;
this._maxWidth =
width -
widthInches -
settings.unwriteableMarginLeft -
settings.unwriteableMarginRight;
@ -2368,6 +2399,16 @@ class MarginsPicker extends PrintUIControlMixin(HTMLElement) {
this._marginError.hidden = true;
}
if (settings.paperSizeUnit !== this._sizeUnit) {
this._sizeUnit = settings.paperSizeUnit;
let unitStr =
this._sizeUnit == settings.kPaperSizeMillimeters ? "mm" : "inches";
for (let elem of this.querySelectorAll("[data-unit-prefix-l10n-id]")) {
let l10nId = elem.getAttribute("data-unit-prefix-l10n-id") + unitStr;
elem.setAttribute("data-l10n-id", l10nId);
}
}
// We need to ensure we don't override the value if the value should be custom.
if (this._marginPicker.value != "custom") {
// Reset the custom margin values if they are not valid and revalidate the form

View File

@ -21,7 +21,7 @@ add_task(async function testSanityCheckPaperList() {
helper.addMockPrinter({ name: mockPrinterName, paperList });
await helper.startPrint();
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await helper.awaitAnimationFrame();
await helper.waitForSettingsEvent();
is(
helper.settings.printerName,
@ -62,7 +62,7 @@ add_task(async function testEmptyPaperListGetsFallbackPaperSizes() {
);
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await helper.awaitAnimationFrame();
await helper.waitForSettingsEvent();
is(
helper.settings.printerName,

View File

@ -800,3 +800,172 @@ add_task(async function testResetMarginPersists() {
await helper.closeDialog();
});
});
add_task(async function testCustomMarginUnits() {
const mockPrinterName = "MetricPrinter";
await PrintHelper.withTestPage(async helper => {
// Add a metric-unit printer we can test with
helper.addMockPrinter({
name: mockPrinterName,
paperSizeUnit: Ci.nsIPrintSettings.kPaperSizeMillimeters,
paperList: [],
});
// settings are saved in inches
const persistedMargins = {
top: 0.5,
right: 5,
bottom: 0.5,
left: 1,
};
await SpecialPowers.pushPrefEnv({
set: [
[
"print.printer_Mozilla_Save_to_PDF.print_margin_right",
persistedMargins.right.toString(),
],
[
"print.printer_Mozilla_Save_to_PDF.print_margin_left",
persistedMargins.left.toString(),
],
[
"print.printer_Mozilla_Save_to_PDF.print_margin_top",
persistedMargins.top.toString(),
],
[
"print.printer_Mozilla_Save_to_PDF.print_margin_bottom",
persistedMargins.bottom.toString(),
],
],
});
await helper.startPrint();
await helper.openMoreSettings();
helper.assertSettingsMatch({
paperId: "na_letter",
marginTop: persistedMargins.top,
marginRight: persistedMargins.right,
marginBottom: persistedMargins.bottom,
marginLeft: persistedMargins.left,
});
is(
helper.settings.printerName,
DEFAULT_PRINTER_NAME,
"The PDF (inch-unit) printer is current"
);
is(
helper.get("margins-picker").value,
"custom",
"The margins picker has the expected value"
);
is(
helper.get("margins-picker").selectedOptions[0].dataset.l10nId,
"printui-margins-custom-inches",
"The custom margins option has correct unit string id"
);
// the unit value should be correct for inches
for (let edgeName of Object.keys(persistedMargins)) {
is(
helper.get(`custom-margin-${edgeName}`).value,
persistedMargins[edgeName].toFixed(2),
`Has the expected unit-converted ${edgeName}-margin value`
);
}
await helper.assertSettingsChanged(
{ marginTop: persistedMargins.top },
{ marginTop: 1 },
async () => {
// update the top margin to 1"
await helper.text(helper.get("custom-margin-top"), "1");
assertPendingMarginsUpdate(helper);
// Wait for the preview to update, the margin options delay updates by
// INPUT_DELAY_MS, which is 500ms.
await helper.waitForSettingsEvent();
// ensure any round-trip correctly re-converts the setting value back to the displayed mm value
is(
helper.get("custom-margin-top").value,
"1",
"Converted custom margin value is expected value"
);
}
);
// put it back to how it was
await helper.text(
helper.get("custom-margin-top"),
persistedMargins.top.toString()
);
await helper.waitForSettingsEvent();
// Now switch to the metric printer
await helper.dispatchSettingsChange({ printerName: mockPrinterName });
await helper.waitForSettingsEvent();
is(
helper.settings.printerName,
mockPrinterName,
"The metric printer is current"
);
is(
helper.get("margins-picker").value,
"custom",
"The margins picker has the expected value"
);
is(
helper.get("margins-picker").selectedOptions[0].dataset.l10nId,
"printui-margins-custom-mm",
"The custom margins option has correct unit string id"
);
// the unit value should be correct for mm
for (let edgeName of Object.keys(persistedMargins)) {
is(
helper.get(`custom-margin-${edgeName}`).value,
(persistedMargins[edgeName] * 25.4).toFixed(2),
`Has the expected unit-converted ${edgeName}-margin value`
);
}
await helper.assertSettingsChanged(
{ marginTop: persistedMargins.top },
{ marginTop: 1 },
async () => {
let marginError = helper.get("error-invalid-margin");
ok(marginError.hidden, "Margin error is hidden");
// update the top margin to 1" in mm
await helper.text(helper.get("custom-margin-top"), "25.4");
// Check the constraints validation is using the right max
// as 25" top margin would be an error, but 25mm is ok
ok(marginError.hidden, "Margin error is hidden");
assertPendingMarginsUpdate(helper);
// Wait for the preview to update, the margin options delay updates by INPUT_DELAY_MS
await helper.waitForSettingsEvent();
// ensure any round-trip correctly re-converts the setting value back to the displayed mm value
is(
helper.get("custom-margin-top").value,
"25.4",
"Converted custom margin value is expected value"
);
}
);
// check margin validation is actually working with unit-appropriate max
await helper.assertSettingsNotChanged({ marginTop: 1 }, async () => {
let marginError = helper.get("error-invalid-margin");
ok(marginError.hidden, "Margin error is hidden");
await helper.text(helper.get("custom-margin-top"), "300");
await BrowserTestUtils.waitForAttributeRemoval("hidden", marginError);
ok(!marginError.hidden, "Margin error is showing");
assertNoPendingMarginsUpdate(helper);
});
await SpecialPowers.popPrefEnv();
await helper.closeDialog();
});
});

View File

@ -1,4 +1,5 @@
const PRINT_DOCUMENT_URI = "chrome://global/content/print.html";
const DEFAULT_PRINTER_NAME = "Mozilla Save to PDF";
const { MockFilePicker } = SpecialPowers;
let pickerMocked = false;
@ -78,13 +79,18 @@ class PrintHelper {
name: "Regular Size",
width: 612,
height: 792,
unwriteableMargin: {
marginTop: 0.1,
marginBottom: 0.1,
marginLeft: 0.1,
marginRight: 0.1,
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaperMargin]),
},
unwriteableMargin: Promise.resolve(
Object.assign(
{
top: 0.1,
bottom: 0.1,
left: 0.1,
right: 0.1,
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaperMargin]),
},
paperProperties.unwriteableMargin
)
),
QueryInterface: ChromeUtils.generateQI([Ci.nsIPaper]),
},
paperProperties
@ -237,18 +243,45 @@ class PrintHelper {
}
let {
name = "Mock Printer",
paperList = [],
paperList,
printerInfoPromise = Promise.resolve(),
paperSizeUnit = Ci.nsIPrintSettings.kPaperSizeInches,
paperId,
} = opts;
let PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].getService(
Ci.nsIPrintSettingsService
);
// Use the fallbackPaperList as the default for mock printers
if (!paperList) {
info("addMockPrinter, using the fallbackPaperList");
paperList = Cc["@mozilla.org/gfx/printerlist;1"].createInstance(
Ci.nsIPrinterList
).fallbackPaperList;
}
let defaultSettings = PSSVC.newPrintSettings;
defaultSettings.printerName = name;
defaultSettings.toFileName = "";
defaultSettings.outputFormat = Ci.nsIPrintSettings.kOutputFormatNative;
defaultSettings.printToFile = false;
defaultSettings.paperSizeUnit = paperSizeUnit;
if (paperId) {
defaultSettings.paperId = paperId;
}
if (
defaultSettings.paperId &&
Array.from(paperList).find(p => p.id == defaultSettings.paperId)
) {
info(
`addMockPrinter, using paperId: ${defaultSettings.paperId} from the paperList`
);
} else if (paperList.length) {
defaultSettings.paperId = paperList[0].id;
info(
`addMockPrinter, corrected default paperId setting value: ${defaultSettings.paperId}`
);
}
let printer = {
name,

View File

@ -68,14 +68,19 @@ printui-margins-default = Default
printui-margins-min = Minimum
printui-margins-none = None
printui-margins-custom-inches = Custom (inches)
printui-margins-custom-mm = Custom (mm)
printui-margins-custom-top = Top
printui-margins-custom-top-inches = Top (inches)
printui-margins-custom-top-mm = Top (mm)
printui-margins-custom-bottom = Bottom
printui-margins-custom-bottom-inches = Bottom (inches)
printui-margins-custom-bottom-mm = Bottom (mm)
printui-margins-custom-left = Left
printui-margins-custom-left-inches = Left (inches)
printui-margins-custom-left-mm = Left (mm)
printui-margins-custom-right = Right
printui-margins-custom-right-inches = Right (inches)
printui-margins-custom-right-mm = Right (mm)
printui-system-dialog-link = Print using the system dialog…