@lvl99dotcom/paintcanvas 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/lib/brushes/configRanges/index.d.ts +17 -0
- package/dist/lib/brushes/configRanges/index.js +31 -1
- package/dist/lib/brushes/params/index.d.ts +2 -1
- package/dist/lib/brushes/params/index.js +7 -4
- package/dist/lib/brushes/types/index.d.ts +8 -0
- package/dist/lib/classes/Layer/index.d.ts +10 -0
- package/dist/lib/classes/Layer/index.js +15 -1
- package/dist/lib/classes/LayerAutosave/index.d.ts +9 -15
- package/dist/lib/classes/LayerAutosave/index.js +30 -43
- package/dist/lib/classes/LayerStack/index.d.ts +15 -0
- package/dist/lib/classes/LayerStack/index.js +26 -2
- package/dist/lib/classes/PaintCanvas/index.d.ts +36 -5
- package/dist/lib/classes/PaintCanvas/index.js +45 -14
- package/dist/lib/classes/PngEncoder/index.d.ts +41 -0
- package/dist/lib/classes/PngEncoder/index.js +104 -0
- package/dist/lib/classes/ProfileGraphs/index.d.ts +87 -0
- package/dist/lib/classes/ProfileGraphs/index.js +148 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +1 -1
- package/dist/lib/classes/SettingsAutosave/index.js +2 -1
- package/dist/lib/classes/UiSettings/index.d.ts +24 -2
- package/dist/lib/classes/UiSettings/index.js +32 -7
- package/dist/lib/messages/schema.d.ts +720 -0
- package/dist/lib/presets/schema.d.ts +360 -0
- package/dist/lib/presets/schema.js +8 -1
- package/dist/lib/profiles/index.d.ts +61 -0
- package/dist/lib/profiles/index.js +131 -0
- package/dist/lib/profiles/schema.d.ts +73 -0
- package/dist/lib/profiles/schema.js +53 -0
- package/dist/lib/rendering/sample/index.d.ts +11 -0
- package/dist/lib/rendering/sample/index.js +36 -5
- package/dist/lib/settings/index.d.ts +2 -1
- package/dist/lib/settings/index.js +4 -1
- package/dist/lib/settings/schema.d.ts +53 -1
- package/dist/lib/settings/schema.js +9 -2
- package/dist/lib/storage/index.d.ts +26 -0
- package/dist/lib/storage/index.js +38 -1
- package/dist/lib/validation/validators.generated.js +13061 -3675
- package/dist/lib/version/index.d.ts +25 -0
- package/dist/lib/version/index.js +35 -0
- package/dist/locales/en-GB.js +35 -0
- package/dist/locales/en-US.js +35 -0
- package/dist/locales/fr.js +35 -0
- package/dist/locales/ja.js +35 -0
- package/dist/locales/ko.js +35 -0
- package/dist/locales/zh-Hans.js +35 -0
- package/dist/locales/zh-Hant.js +35 -0
- package/dist/package.js +1 -1
- package/dist/ui/ask/index.d.ts +48 -0
- package/dist/ui/ask/index.js +67 -0
- package/dist/ui/base/index.d.ts +8 -1
- package/dist/ui/base/index.js +19 -4
- package/dist/ui/elements/PaintCanvas/index.d.ts +13 -3
- package/dist/ui/elements/PaintCanvas/index.js +25 -6
- package/dist/ui/elements/PaintCanvas/style.js +1 -1
- package/dist/ui/elements/PcAppSettings/index.d.ts +15 -7
- package/dist/ui/elements/PcAppSettings/index.js +53 -62
- package/dist/ui/elements/PcBrushConfig/index.d.ts +26 -14
- package/dist/ui/elements/PcBrushConfig/index.js +214 -145
- package/dist/ui/elements/PcBrushConfig/style.js +1 -1
- package/dist/ui/elements/PcBrushTest/index.d.ts +1 -0
- package/dist/ui/elements/PcBrushTest/index.js +15 -9
- package/dist/ui/elements/PcBrushTest/style.js +1 -1
- package/dist/ui/elements/PcButton/index.d.ts +12 -3
- package/dist/ui/elements/PcButton/index.js +18 -10
- package/dist/ui/elements/PcButtonMenu/index.d.ts +88 -0
- package/dist/ui/elements/PcButtonMenu/index.js +125 -0
- package/dist/ui/elements/PcCanvas/index.d.ts +15 -1
- package/dist/ui/elements/PcCanvas/index.js +42 -19
- package/dist/ui/elements/PcCanvas/style.js +1 -1
- package/dist/ui/elements/PcClipboardTools/index.d.ts +11 -7
- package/dist/ui/elements/PcClipboardTools/index.js +30 -29
- package/dist/ui/elements/PcDialog/index.d.ts +46 -10
- package/dist/ui/elements/PcDialog/index.js +102 -51
- package/dist/ui/elements/PcDialogWindow/index.d.ts +141 -0
- package/dist/ui/elements/PcDialogWindow/index.js +385 -0
- package/dist/ui/elements/PcInputSettings/index.d.ts +2 -1
- package/dist/ui/elements/PcInputSettings/index.js +9 -15
- package/dist/ui/elements/PcLayerItem/index.d.ts +21 -6
- package/dist/ui/elements/PcLayerItem/index.js +53 -26
- package/dist/ui/elements/PcLayerItem/style.js +1 -1
- package/dist/ui/elements/PcPanelBrushes/index.d.ts +3 -2
- package/dist/ui/elements/PcPanelBrushes/index.js +7 -5
- package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
- package/dist/ui/elements/PcPanelColours/index.js +2 -2
- package/dist/ui/elements/PcPanelColours/style.js +1 -1
- package/dist/ui/elements/PcPanelLayers/index.js +1 -1
- package/dist/ui/elements/PcPanelLayers/style.js +1 -1
- package/dist/ui/elements/PcProfileEditor/index.d.ts +103 -0
- package/dist/ui/elements/PcProfileEditor/index.js +259 -0
- package/dist/ui/elements/PcProfileGraph/index.d.ts +84 -0
- package/dist/ui/elements/PcProfileGraph/index.js +317 -0
- package/dist/ui/elements/PcShortcutSettings/index.js +9 -13
- package/dist/ui/elements/PcSliderRange/index.d.ts +147 -0
- package/dist/ui/elements/PcSliderRange/index.js +308 -0
- package/dist/ui/elements/PcStats/index.d.ts +19 -4
- package/dist/ui/elements/PcStats/index.js +29 -13
- package/dist/ui/elements/PcToggleCheckbox/index.d.ts +13 -2
- package/dist/ui/elements/PcToggleCheckbox/index.js +27 -8
- package/dist/ui/elements/PcToolSettings/index.d.ts +1 -0
- package/dist/ui/elements/PcToolSettings/index.js +14 -14
- package/dist/ui/elements/PcVersion/index.d.ts +12 -0
- package/dist/ui/elements/PcVersion/index.js +43 -0
- package/dist/ui/icons/images/icon-profile-graph@2x.js +3 -0
- package/dist/ui/icons/index.d.ts +1 -1
- package/dist/ui/icons/index.js +2 -0
- package/dist/ui/index.d.ts +9 -2
- package/dist/ui/index.js +9 -2
- package/dist/ui/layout/index.d.ts +2 -2
- package/dist/ui/layout/index.js +2 -2
- package/dist/ui/styles/index.d.ts +21 -1
- package/dist/ui/styles/index.js +73 -14
- package/locales/en-GB.json +35 -0
- package/locales/en-US.json +35 -0
- package/locales/fr.json +35 -0
- package/locales/ja.json +35 -0
- package/locales/ko.json +35 -0
- package/locales/zh-Hans.json +35 -0
- package/locales/zh-Hant.json +35 -0
- package/package.json +25 -23
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "../elements/PcDialog";
|
|
2
|
+
import type Translations from "../../lib/i18n";
|
|
3
|
+
import { type DialogField } from "../elements/PcDialog";
|
|
4
|
+
/** The choice that agrees, in the dialogs `askConfirm` and `askText` show */
|
|
5
|
+
export declare const OK_CHOICE = "ok";
|
|
6
|
+
/** What to ask */
|
|
7
|
+
export interface AskOptions {
|
|
8
|
+
heading: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
/** The button that agrees */
|
|
11
|
+
confirm: string;
|
|
12
|
+
/** The button that doesn't */
|
|
13
|
+
cancel: string;
|
|
14
|
+
/** Whether agreeing removes or replaces something (the button is pink) */
|
|
15
|
+
cancelling?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** What to ask for text: as `AskOptions`, with the field's label and the text it starts with */
|
|
18
|
+
export interface AskTextOptions extends AskOptions, DialogField {
|
|
19
|
+
}
|
|
20
|
+
/** Asks the user to confirm, resolving true if they agree */
|
|
21
|
+
export type ConfirmFn = (options: AskOptions) => boolean | Promise<boolean>;
|
|
22
|
+
/** Asks the user for text, resolving with it, or null if they don't give it */
|
|
23
|
+
export type PromptFn = (options: AskTextOptions) => string | null | Promise<string | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Ask the user to confirm in a dialog shown in `parent`, resolving true if they agree (false for the cancel button,
|
|
26
|
+
* Escape or a press outside it).
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* if (await askConfirm(this.renderRoot, { heading: "Delete preset", message: 'Delete "Ink"?', confirm: "Delete",
|
|
30
|
+
* cancel: "Cancel", cancelling: true })) remove();
|
|
31
|
+
*/
|
|
32
|
+
export declare const askConfirm: (parent: Node, options: AskOptions) => Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Ask the user for text in a dialog shown in `parent`, resolving with what they typed when they agree (or press Enter),
|
|
35
|
+
* or null if they cancel.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const name = await askText(this.renderRoot, { heading: "Add to presets", label: "Name", value: "Ink",
|
|
39
|
+
* confirm: "Save", cancel: "Cancel" });
|
|
40
|
+
*/
|
|
41
|
+
export declare const askText: (parent: Node, { label, value, ...options }: AskTextOptions) => Promise<string | null>;
|
|
42
|
+
/**
|
|
43
|
+
* The question asked before deleting one of the user's brush presets, in the chosen language.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* await askConfirm(this.renderRoot, deletePresetQuestion(this.translations, "Ink"));
|
|
47
|
+
*/
|
|
48
|
+
export declare const deletePresetQuestion: (translations: Pick<Translations, "t">, name: string) => AskOptions;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { CANCEL_CHOICE } from "../elements/PcDialog/index.js";
|
|
2
|
+
// src/ui/ask/index.ts
|
|
3
|
+
/** The choice that agrees, in the dialogs `askConfirm` and `askText` show */
|
|
4
|
+
var OK_CHOICE = "ok";
|
|
5
|
+
/**
|
|
6
|
+
* Show a dialog in a parent (e.g. an element's shadow root) until the user chooses, then remove it. The choice doesn't
|
|
7
|
+
* reach the parent's listeners.
|
|
8
|
+
*/
|
|
9
|
+
var ask = (parent, options, field) => new Promise((resolve) => {
|
|
10
|
+
const dialog = document.createElement("pc-dialog");
|
|
11
|
+
dialog.heading = options.heading;
|
|
12
|
+
dialog.message = options.message ?? "";
|
|
13
|
+
dialog.field = field;
|
|
14
|
+
dialog.choices = [{
|
|
15
|
+
value: "ok",
|
|
16
|
+
label: options.confirm,
|
|
17
|
+
cancelling: options.cancelling
|
|
18
|
+
}, {
|
|
19
|
+
value: CANCEL_CHOICE,
|
|
20
|
+
label: options.cancel,
|
|
21
|
+
variant: "dismiss"
|
|
22
|
+
}];
|
|
23
|
+
dialog.addEventListener("pc-choose", (event) => {
|
|
24
|
+
event.stopPropagation();
|
|
25
|
+
dialog.remove();
|
|
26
|
+
resolve(event.detail);
|
|
27
|
+
}, { once: true });
|
|
28
|
+
parent.appendChild(dialog);
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Ask the user to confirm in a dialog shown in `parent`, resolving true if they agree (false for the cancel button,
|
|
32
|
+
* Escape or a press outside it).
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* if (await askConfirm(this.renderRoot, { heading: "Delete preset", message: 'Delete "Ink"?', confirm: "Delete",
|
|
36
|
+
* cancel: "Cancel", cancelling: true })) remove();
|
|
37
|
+
*/
|
|
38
|
+
var askConfirm = async (parent, options) => (await ask(parent, options)).value === "ok";
|
|
39
|
+
/**
|
|
40
|
+
* Ask the user for text in a dialog shown in `parent`, resolving with what they typed when they agree (or press Enter),
|
|
41
|
+
* or null if they cancel.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* const name = await askText(this.renderRoot, { heading: "Add to presets", label: "Name", value: "Ink",
|
|
45
|
+
* confirm: "Save", cancel: "Cancel" });
|
|
46
|
+
*/
|
|
47
|
+
var askText = async (parent, { label, value, ...options }) => {
|
|
48
|
+
const choice = await ask(parent, options, {
|
|
49
|
+
label,
|
|
50
|
+
value
|
|
51
|
+
});
|
|
52
|
+
return choice.value === "ok" ? choice.text : null;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* The question asked before deleting one of the user's brush presets, in the chosen language.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* await askConfirm(this.renderRoot, deletePresetQuestion(this.translations, "Ink"));
|
|
59
|
+
*/
|
|
60
|
+
var deletePresetQuestion = (translations, name) => ({
|
|
61
|
+
heading: translations.t("paintCanvas.presets.deleteHeading"),
|
|
62
|
+
message: translations.t("paintCanvas.presets.deleteConfirm", { name }),
|
|
63
|
+
confirm: translations.t("paintCanvas.common.delete"),
|
|
64
|
+
cancel: translations.t("paintCanvas.common.cancel"),
|
|
65
|
+
cancelling: true
|
|
66
|
+
});
|
|
67
|
+
export { OK_CHOICE, askConfirm, askText, deletePresetQuestion };
|
package/dist/ui/base/index.d.ts
CHANGED
|
@@ -16,8 +16,15 @@ export declare const defineElement: (name: string, constructor: CustomElementCon
|
|
|
16
16
|
* emit(this, "pc-select", { value: "duplicate" });
|
|
17
17
|
*/
|
|
18
18
|
export declare const emit: <T>(target: EventTarget, type: string, detail?: T) => boolean;
|
|
19
|
+
/** The least font size of form fields on touch screens: iOS zooms the page in on fields with smaller text */
|
|
20
|
+
export declare const TOUCH_FIELD_FONT_SIZE = "16px";
|
|
19
21
|
/**
|
|
20
|
-
*
|
|
22
|
+
* Form fields' text on touch screens: at least 16px, so iOS doesn't zoom the page in when one is focused (which is
|
|
23
|
+
* hard to undo). It wins over elements' own field sizes, as zooming makes the whole interface hard to use.
|
|
24
|
+
*/
|
|
25
|
+
export declare const touchFields: import("lit").CSSResult;
|
|
26
|
+
/**
|
|
27
|
+
* The base of PaintCanvas's elements: the design tokens, 16px form fields on touch screens (see `touchFields`), the translations and icons they use (shared ones unless
|
|
21
28
|
* given others), and re-rendering when either changes.
|
|
22
29
|
*
|
|
23
30
|
* @example
|
package/dist/ui/base/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { installTokens, tokens } from "../tokens/index.js";
|
|
2
2
|
import { icons } from "../icons/index.js";
|
|
3
3
|
import { translations } from "../../lib/i18n/index.js";
|
|
4
|
-
import { LitElement } from "lit";
|
|
4
|
+
import { LitElement, css, unsafeCSS } from "lit";
|
|
5
5
|
// src/ui/base/index.ts
|
|
6
6
|
/**
|
|
7
7
|
* Register a custom element unless the name is already registered (e.g. by another copy of PaintCanvas, or after hot
|
|
@@ -25,8 +25,23 @@ var emit = (target, type, detail) => target.dispatchEvent(new CustomEvent(type,
|
|
|
25
25
|
composed: true,
|
|
26
26
|
cancelable: true
|
|
27
27
|
}));
|
|
28
|
+
/** The least font size of form fields on touch screens: iOS zooms the page in on fields with smaller text */
|
|
29
|
+
var TOUCH_FIELD_FONT_SIZE = "16px";
|
|
28
30
|
/**
|
|
29
|
-
*
|
|
31
|
+
* Form fields' text on touch screens: at least 16px, so iOS doesn't zoom the page in when one is focused (which is
|
|
32
|
+
* hard to undo). It wins over elements' own field sizes, as zooming makes the whole interface hard to use.
|
|
33
|
+
*/
|
|
34
|
+
var touchFields = css`
|
|
35
|
+
@media (pointer: coarse) {
|
|
36
|
+
input,
|
|
37
|
+
select,
|
|
38
|
+
textarea {
|
|
39
|
+
font-size: max(${unsafeCSS(TOUCH_FIELD_FONT_SIZE)}, 1em) !important;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
/**
|
|
44
|
+
* The base of PaintCanvas's elements: the design tokens, 16px form fields on touch screens (see `touchFields`), the translations and icons they use (shared ones unless
|
|
30
45
|
* given others), and re-rendering when either changes.
|
|
31
46
|
*
|
|
32
47
|
* @example
|
|
@@ -37,7 +52,7 @@ var emit = (target, type, detail) => target.dispatchEvent(new CustomEvent(type,
|
|
|
37
52
|
* }
|
|
38
53
|
*/
|
|
39
54
|
var PcElement = class extends LitElement {
|
|
40
|
-
static styles = [tokens];
|
|
55
|
+
static styles = [tokens, touchFields];
|
|
41
56
|
static properties = {
|
|
42
57
|
translations: { attribute: false },
|
|
43
58
|
icons: { attribute: false },
|
|
@@ -91,4 +106,4 @@ var PcElement = class extends LitElement {
|
|
|
91
106
|
this.watched = [];
|
|
92
107
|
}
|
|
93
108
|
};
|
|
94
|
-
export { PcElement, defineElement, emit };
|
|
109
|
+
export { PcElement, TOUCH_FIELD_FONT_SIZE, defineElement, emit, touchFields };
|
|
@@ -23,7 +23,8 @@ import "../PcDialog";
|
|
|
23
23
|
* - `left`: `<pc-toolbar>` (a pane) by default; toolbars in the sides are minimised (their tools one button that opens a
|
|
24
24
|
* menu of them) while the layout is narrow
|
|
25
25
|
* - `top`: a horizontal `<pc-pane>` with `<pc-tool-settings>` (for tools that have settings) and, at its end,
|
|
26
|
-
* `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow
|
|
26
|
+
* `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow or the window is narrower than
|
|
27
|
+
* 900px) by default
|
|
27
28
|
* - `right`: a `<pc-pane>` with `<pc-panel-layers>` by default
|
|
28
29
|
* - `center`: `<pc-canvas>` by default
|
|
29
30
|
* - `overlay`: drawn over the canvas; `<pc-canvas-map>` by default
|
|
@@ -36,7 +37,7 @@ import "../PcDialog";
|
|
|
36
37
|
* does by default), the toolbar has no layers menu button.
|
|
37
38
|
*
|
|
38
39
|
* Each side has a mode, chosen by the layout's width from `left-modes` and `right-modes` (default `"docked,
|
|
39
|
-
*
|
|
40
|
+
* floating@600"`), which the layout gives the side's `<pc-pane>`s (see `PcPane`): `docked` beside the canvas; `rail`, a
|
|
40
41
|
* column of buttons (one per panel) that open each panel over the canvas; `floating`, the pane over the canvas as a
|
|
41
42
|
* box that collapses to a button; or `overlay`, a rail over the canvas without a background (the canvas fills the
|
|
42
43
|
* width behind it). Give side content in a `<pc-pane>` to have it follow the side's mode.
|
|
@@ -50,7 +51,9 @@ import "../PcDialog";
|
|
|
50
51
|
* that offers to draw here instead. Fires `pc-toast` when the drawing can't be loaded or saved.
|
|
51
52
|
*
|
|
52
53
|
* With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette, colours,
|
|
53
|
-
* theme and
|
|
54
|
+
* theme, language and rendering) are kept in the browser under that name (see `SettingsAutosave`). Fires `pc-toast` when
|
|
55
|
+
* they can't be. The rendering chosen there is also kept in `localStorage` (see `saveRenderingChoice`), so the canvas the
|
|
56
|
+
* layout makes draws where the user last chose (see `PaintCanvasOptions.rendering`).
|
|
54
57
|
*
|
|
55
58
|
* @example
|
|
56
59
|
* html`<paint-canvas style="height: 600px"></paint-canvas>`
|
|
@@ -154,6 +157,8 @@ export declare class PaintCanvasElement extends PcElement {
|
|
|
154
157
|
private watchedAutosave?;
|
|
155
158
|
/** Keeps the app settings under the `settings-store` name, if any */
|
|
156
159
|
private ownSettingsAutosave?;
|
|
160
|
+
/** Stops keeping the rendering chosen in the canvas's UI settings under the `settings-store` name, if kept */
|
|
161
|
+
private stopKeepingRendering?;
|
|
157
162
|
/** Whether drawing was blocked when shortcuts were last watched */
|
|
158
163
|
private blockedShortcuts;
|
|
159
164
|
/** Whether each side's slot has a layers menu (the toolbar's isn't needed then) */
|
|
@@ -204,6 +209,11 @@ export declare class PaintCanvasElement extends PcElement {
|
|
|
204
209
|
* saves any change waiting to be saved).
|
|
205
210
|
*/
|
|
206
211
|
private useSettingsStore;
|
|
212
|
+
/**
|
|
213
|
+
* Keep the rendering chosen in the canvas's UI settings (e.g. when they're restored, imported or changed) under a
|
|
214
|
+
* name, for the next time the layout makes a canvas. Returns what stops it.
|
|
215
|
+
*/
|
|
216
|
+
private keepRendering;
|
|
207
217
|
/** Show errors from the canvas's current autosave */
|
|
208
218
|
private watchAutosaveErrors;
|
|
209
219
|
/** Handle keyboard shortcuts for the current canvas, if asked to (not while blocked) */
|
|
@@ -5,7 +5,7 @@ import ChangeController from "../../ChangeController/index.js";
|
|
|
5
5
|
import PaintCanvas, { Panel } from "../../../lib/classes/PaintCanvas/index.js";
|
|
6
6
|
import KeyboardShortcuts, { SHORTCUT_EVENT } from "../../../lib/classes/KeyboardShortcuts/index.js";
|
|
7
7
|
import { isTouchDevice } from "../../../lib/classes/InputSettings/index.js";
|
|
8
|
-
import IndexedDbLayerStore, { IndexedDbSettingsStore } from "../../../lib/storage/index.js";
|
|
8
|
+
import IndexedDbLayerStore, { IndexedDbSettingsStore, loadRenderingChoice, saveRenderingChoice } from "../../../lib/storage/index.js";
|
|
9
9
|
import SettingsAutosave, { SETTINGS_AUTOSAVE_ERROR_EVENT } from "../../../lib/classes/SettingsAutosave/index.js";
|
|
10
10
|
import { AUTOSAVE_ERROR_EVENT, AutosaveState } from "../../../lib/classes/LayerAutosave/index.js";
|
|
11
11
|
import { isOwnAuthor } from "../../../lib/brushes/authors/index.js";
|
|
@@ -45,7 +45,8 @@ var TAKE_OVER_CHOICE = "take-over";
|
|
|
45
45
|
* - `left`: `<pc-toolbar>` (a pane) by default; toolbars in the sides are minimised (their tools one button that opens a
|
|
46
46
|
* menu of them) while the layout is narrow
|
|
47
47
|
* - `top`: a horizontal `<pc-pane>` with `<pc-tool-settings>` (for tools that have settings) and, at its end,
|
|
48
|
-
* `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow
|
|
48
|
+
* `<pc-clipboard-tools>` (cut, copy and paste; a ⋮ menu while the layout is narrow or the window is narrower than
|
|
49
|
+
* 900px) by default
|
|
49
50
|
* - `right`: a `<pc-pane>` with `<pc-panel-layers>` by default
|
|
50
51
|
* - `center`: `<pc-canvas>` by default
|
|
51
52
|
* - `overlay`: drawn over the canvas; `<pc-canvas-map>` by default
|
|
@@ -58,7 +59,7 @@ var TAKE_OVER_CHOICE = "take-over";
|
|
|
58
59
|
* does by default), the toolbar has no layers menu button.
|
|
59
60
|
*
|
|
60
61
|
* Each side has a mode, chosen by the layout's width from `left-modes` and `right-modes` (default `"docked,
|
|
61
|
-
*
|
|
62
|
+
* floating@600"`), which the layout gives the side's `<pc-pane>`s (see `PcPane`): `docked` beside the canvas; `rail`, a
|
|
62
63
|
* column of buttons (one per panel) that open each panel over the canvas; `floating`, the pane over the canvas as a
|
|
63
64
|
* box that collapses to a button; or `overlay`, a rail over the canvas without a background (the canvas fills the
|
|
64
65
|
* width behind it). Give side content in a `<pc-pane>` to have it follow the side's mode.
|
|
@@ -72,7 +73,9 @@ var TAKE_OVER_CHOICE = "take-over";
|
|
|
72
73
|
* that offers to draw here instead. Fires `pc-toast` when the drawing can't be loaded or saved.
|
|
73
74
|
*
|
|
74
75
|
* With a `settings-store` name, the user's app settings (input settings, keyboard shortcuts, colour palette, colours,
|
|
75
|
-
* theme and
|
|
76
|
+
* theme, language and rendering) are kept in the browser under that name (see `SettingsAutosave`). Fires `pc-toast` when
|
|
77
|
+
* they can't be. The rendering chosen there is also kept in `localStorage` (see `saveRenderingChoice`), so the canvas the
|
|
78
|
+
* layout makes draws where the user last chose (see `PaintCanvasOptions.rendering`).
|
|
76
79
|
*
|
|
77
80
|
* @example
|
|
78
81
|
* html`<paint-canvas style="height: 600px"></paint-canvas>`
|
|
@@ -127,6 +130,8 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
127
130
|
watchedAutosave;
|
|
128
131
|
/** Keeps the app settings under the `settings-store` name, if any */
|
|
129
132
|
ownSettingsAutosave;
|
|
133
|
+
/** Stops keeping the rendering chosen in the canvas's UI settings under the `settings-store` name, if kept */
|
|
134
|
+
stopKeepingRendering;
|
|
130
135
|
/** Whether drawing was blocked when shortcuts were last watched */
|
|
131
136
|
blockedShortcuts = false;
|
|
132
137
|
/** Whether each side's slot has a layers menu (the toolbar's isn't needed then) */
|
|
@@ -194,7 +199,7 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
194
199
|
return sideModeFor(parseSideModes(side === "left" ? this.leftModes : this.rightModes), this.width);
|
|
195
200
|
}
|
|
196
201
|
connectedCallback() {
|
|
197
|
-
this.app ??= new PaintCanvas();
|
|
202
|
+
this.app ??= new PaintCanvas({ rendering: this.settingsStore ? loadRenderingChoice(this.settingsStore) : void 0 });
|
|
198
203
|
super.connectedCallback();
|
|
199
204
|
this.resizeObserver?.observe(this);
|
|
200
205
|
this.addEventListener("pointerdown", this.onPointerDown, true);
|
|
@@ -284,10 +289,22 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
284
289
|
*/
|
|
285
290
|
useSettingsStore() {
|
|
286
291
|
this.ownSettingsAutosave?.stop();
|
|
292
|
+
this.stopKeepingRendering?.();
|
|
287
293
|
const name = this.settingsStore || void 0;
|
|
294
|
+
this.stopKeepingRendering = name === void 0 ? void 0 : this.keepRendering(name);
|
|
288
295
|
this.ownSettingsAutosave = name === void 0 ? void 0 : new SettingsAutosave(this.app, new IndexedDbSettingsStore(name));
|
|
289
296
|
this.ownSettingsAutosave?.addEventListener(SETTINGS_AUTOSAVE_ERROR_EVENT, this.onSettingsAutosaveError);
|
|
290
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Keep the rendering chosen in the canvas's UI settings (e.g. when they're restored, imported or changed) under a
|
|
300
|
+
* name, for the next time the layout makes a canvas. Returns what stops it.
|
|
301
|
+
*/
|
|
302
|
+
keepRendering(name) {
|
|
303
|
+
const ui = this.app.ui;
|
|
304
|
+
const keep = () => saveRenderingChoice(name, ui.data.rendering);
|
|
305
|
+
ui.addEventListener("change", keep);
|
|
306
|
+
return () => ui.removeEventListener("change", keep);
|
|
307
|
+
}
|
|
291
308
|
/** Show errors from the canvas's current autosave */
|
|
292
309
|
watchAutosaveErrors() {
|
|
293
310
|
const autosave = this.app?.autosave;
|
|
@@ -433,7 +450,7 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
433
450
|
closePanelOutside(event) {
|
|
434
451
|
const panel = this.app?.panel;
|
|
435
452
|
if (!panel) return;
|
|
436
|
-
if (event.composedPath().some((target) => target instanceof Element && (target.classList.contains("panel") && target.getRootNode() === this.renderRoot || target.matches("dialog, pc-dialog") || target.getAttribute("data-panel") === panel || panel === Panel.Palette && target.localName === "pc-colour-pair"))) return;
|
|
453
|
+
if (event.composedPath().some((target) => target instanceof Element && (target.classList.contains("panel") && target.getRootNode() === this.renderRoot || target.matches("dialog, pc-dialog, pc-dialog-window") || target.getAttribute("data-panel") === panel || panel === Panel.Palette && target.localName === "pc-colour-pair"))) return;
|
|
437
454
|
markDismissingPress(event);
|
|
438
455
|
this.app.closePanel();
|
|
439
456
|
}
|
|
@@ -484,6 +501,8 @@ var PaintCanvasElement = class extends PcElement {
|
|
|
484
501
|
}];
|
|
485
502
|
return html`<pc-dialog
|
|
486
503
|
class="elsewhere"
|
|
504
|
+
inline
|
|
505
|
+
.dismissible=${false}
|
|
487
506
|
heading=${this.t("paintCanvas.autosave.elsewhere")}
|
|
488
507
|
message=${this.t("paintCanvas.autosave.elsewhereMessage")}
|
|
489
508
|
.choices=${choices}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/ui/elements/PaintCanvas/style.css?inline
|
|
2
|
-
var style_default = "/* The layout: header across the top, footer across the bottom, sides left and right, and between them the tool\n settings, the canvas and the bottom bar. Empty areas take no space. */\n:host {\n position: relative;\n display: grid;\n grid-template:\n \"header header header\" auto\n \"left top right\" auto\n \"left center right\" 1fr\n \"left bottom right\" auto\n \"footer footer footer\" auto / auto 1fr auto;\n overflow: hidden;\n background: var(--pc-bar);\n font-family: var(--pc-font);\n font-size: var(--pc-font-size);\n}\nheader {\n grid-area: header;\n}\n.top {\n grid-area: top;\n min-width: 0;\n}\n/* The tool settings fill the top pane */\n.top pc-tool-settings {\n flex: 1;\n}\n.center {\n position: relative;\n grid-area: center;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.bottom {\n grid-area: bottom;\n min-width: 0;\n}\nfooter {\n grid-area: footer;\n}\n.side {\n position: relative;\n z-index: 3;\n display: flex;\n min-height: 0;\n}\n/* A side's panes fill it */\n.side pc-pane,\n.side pc-toolbar,\n.side ::slotted(*) {\n flex: 1;\n}\n.side.left {\n grid-area: left;\n}\n.side.right {\n grid-area: right;\n}\n\n/* Hiding the interface (Tab key) leaves only the canvas */\n:host([ui-hidden]) header,\n:host([ui-hidden]) .top,\n:host([ui-hidden]) .bottom,\n:host([ui-hidden]) footer,\n:host([ui-hidden]) .side {\n display: none;\n}\n\n/* The canvas fills the middle; things drawn over it go in the overlay */\n.center ::slotted([slot=\"center\"]),\n.center pc-canvas {\n position: absolute;\n inset: 0;\n}\n.overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.overlay > * {\n pointer-events: auto;\n}\npc-canvas-map {\n position: absolute;\n right: 20px;\n bottom: 20px;\n}\n\n/* Menus opened from the toolbar float over the canvas, beside the toolbar */\n.panel {\n position: absolute;\n z-index: 4;\n left: 0;\n bottom: 0;\n max-height: 100%;\n overflow: auto;\n}\n.panel.top-panel {\n top: 0;\n bottom: auto;\n}\n/* The app menu: the implementer's content in a panel */\n.menu-panel:not([open]) {\n display: none;\n}\n\n/* Floating: the side's panes float over the canvas (see pc-pane), so the side takes no space */\n.side[data-mode=\"floating\"] {\n /* Beside the canvas only, so it floats over the canvas and not the tool settings */\n grid-row: 3;\n width: 0;\n}\n/* Overlay: the side's rail sits over the canvas (beside it only, not the tool settings), so the canvas fills the\n width behind it; presses between its panes' buttons (which take presses themselves) reach the canvas */\n.side[data-mode=\"overlay\"] {\n grid-row: 3;\n grid-column: 1 / -1;\n pointer-events: none;\n}\n.side.left[data-mode=\"overlay\"] {\n justify-self: start;\n}\n.side.right[data-mode=\"overlay\"] {\n justify-self: end;\n}\n/* The toolbar's panels open beside a left overlay rail, not under it */\n:host([left-mode=\"overlay\"]) .panel {\n left: var(--pc-left-inset);\n}\n
|
|
2
|
+
var style_default = "/* The layout: header across the top, footer across the bottom, sides left and right, and between them the tool\n settings, the canvas and the bottom bar. Empty areas take no space. */\n:host {\n position: relative;\n display: grid;\n grid-template:\n \"header header header\" auto\n \"left top right\" auto\n \"left center right\" 1fr\n \"left bottom right\" auto\n \"footer footer footer\" auto / auto 1fr auto;\n overflow: hidden;\n background: var(--pc-bar);\n font-family: var(--pc-font);\n font-size: var(--pc-font-size);\n}\nheader {\n grid-area: header;\n}\n.top {\n grid-area: top;\n min-width: 0;\n}\n/* The tool settings fill the top pane */\n.top pc-tool-settings {\n flex: 1;\n}\n.center {\n position: relative;\n grid-area: center;\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n}\n.bottom {\n grid-area: bottom;\n min-width: 0;\n}\nfooter {\n grid-area: footer;\n}\n.side {\n position: relative;\n z-index: 3;\n display: flex;\n min-height: 0;\n}\n/* A side's panes fill it */\n.side pc-pane,\n.side pc-toolbar,\n.side ::slotted(*) {\n flex: 1;\n}\n.side.left {\n grid-area: left;\n}\n.side.right {\n grid-area: right;\n}\n\n/* Hiding the interface (Tab key) leaves only the canvas */\n:host([ui-hidden]) header,\n:host([ui-hidden]) .top,\n:host([ui-hidden]) .bottom,\n:host([ui-hidden]) footer,\n:host([ui-hidden]) .side {\n display: none;\n}\n\n/* The canvas fills the middle; things drawn over it go in the overlay */\n.center ::slotted([slot=\"center\"]),\n.center pc-canvas {\n position: absolute;\n inset: 0;\n}\n.overlay {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n.overlay > * {\n pointer-events: auto;\n}\npc-canvas-map {\n position: absolute;\n right: 20px;\n bottom: 20px;\n}\n\n/* Menus opened from the toolbar float over the canvas, beside the toolbar */\n.panel {\n position: absolute;\n z-index: 4;\n left: 0;\n bottom: 0;\n max-height: 100%;\n overflow: auto;\n}\n.panel.top-panel {\n top: 0;\n bottom: auto;\n}\n/* The app menu: the implementer's content in a panel */\n.menu-panel:not([open]) {\n display: none;\n}\n\n/* Floating: the side's panes float over the canvas (see pc-pane), so the side takes no space */\n.side[data-mode=\"floating\"] {\n /* Beside the canvas only, so it floats over the canvas and not the tool settings */\n grid-row: 3;\n width: 0;\n}\n/* Overlay: the side's rail sits over the canvas (beside it only, not the tool settings), so the canvas fills the\n width behind it; presses between its panes' buttons (which take presses themselves) reach the canvas */\n.side[data-mode=\"overlay\"] {\n grid-row: 3;\n grid-column: 1 / -1;\n pointer-events: none;\n}\n.side.left[data-mode=\"overlay\"] {\n justify-self: start;\n}\n.side.right[data-mode=\"overlay\"] {\n justify-self: end;\n}\n/* The toolbar's panels open beside a left overlay rail, not under it */\n:host([left-mode=\"overlay\"]) .panel {\n left: var(--pc-left-inset);\n}\n";
|
|
3
3
|
export { style_default as default };
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
import { nothing
|
|
1
|
+
import { nothing } from "lit";
|
|
2
2
|
import { PcElement } from "../../base";
|
|
3
3
|
import "../PcShortcutSettings";
|
|
4
|
+
import "../PcToggleCheckbox";
|
|
5
|
+
import "../PcDialogWindow";
|
|
4
6
|
import type PaintCanvas from "../../../lib/classes/PaintCanvas";
|
|
5
7
|
import { type SaveMethod } from "../../../lib/rendering/screenshot";
|
|
6
8
|
/**
|
|
7
|
-
*
|
|
9
|
+
* The user's app settings: a "Draw with the GPU" switch (the user's `ui.data.rendering`, used from the next start, so it
|
|
10
|
+
* says when the page needs reloading), and buttons: "Keyboard shortcuts", which opens a window to change them (see
|
|
8
11
|
* `pc-shortcut-settings`), and "Import settings" and "Export settings", which read and write a settings JSON file (input
|
|
9
|
-
* settings, keyboard shortcuts, colour palette, colours, theme and
|
|
10
|
-
* closes with its
|
|
11
|
-
* exporting fails.
|
|
12
|
+
* settings, keyboard shortcuts, colour palette, colours, profile graphs, theme, language and rendering). The window is a shaded
|
|
13
|
+
* `<pc-dialog-window>` over the whole page; it closes with its ⨉ button, Escape or a press outside it, and focus goes
|
|
14
|
+
* back to the button. Fires `pc-toast` after importing, or when importing or exporting fails.
|
|
12
15
|
*
|
|
13
16
|
* @example
|
|
14
17
|
* html`<pc-app-settings .app=${canvas}></pc-app-settings>`
|
|
@@ -39,8 +42,8 @@ export declare class PcAppSettings extends PcElement {
|
|
|
39
42
|
shortcutsOpen: boolean;
|
|
40
43
|
/** Saves exported files (replaceable for tests) */
|
|
41
44
|
saveFile: (blob: Blob, name: string) => Promise<SaveMethod | undefined>;
|
|
45
|
+
private changes;
|
|
42
46
|
constructor();
|
|
43
|
-
protected updated(changed: PropertyValues<this>): void;
|
|
44
47
|
/** Close the keyboard shortcuts window */
|
|
45
48
|
closeShortcuts(): void;
|
|
46
49
|
/**
|
|
@@ -53,7 +56,12 @@ export declare class PcAppSettings extends PcElement {
|
|
|
53
56
|
exportFile(): Promise<void>;
|
|
54
57
|
/** Show a settings file error (one of `SETTINGS_FILE_ERRORS`) in the chosen language */
|
|
55
58
|
private toastError;
|
|
56
|
-
/** The keyboard shortcuts window
|
|
59
|
+
/** The keyboard shortcuts window, with its contents only while open */
|
|
57
60
|
private renderShortcuts;
|
|
61
|
+
/**
|
|
62
|
+
* The switch that draws with the GPU (or the CPU) from the next start, saying when the page needs reloading to use
|
|
63
|
+
* the choice (see `PaintCanvas.rendering`).
|
|
64
|
+
*/
|
|
65
|
+
private renderRendering;
|
|
58
66
|
render(): import("lit").TemplateResult<1> | typeof nothing;
|
|
59
67
|
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { SETTINGS_FILE_FORMAT } from "../../../lib/settings/schema.js";
|
|
2
2
|
import { ICON_CONTROLS_CSS, PILLS_CSS, WINDOWS_CSS } from "../../styles/index.js";
|
|
3
3
|
import { PcElement, defineElement, emit } from "../../base/index.js";
|
|
4
|
+
import ChangeController from "../../ChangeController/index.js";
|
|
4
5
|
import "../PcShortcutSettings/index.js";
|
|
6
|
+
import "../PcToggleCheckbox/index.js";
|
|
7
|
+
import "../PcDialogWindow/index.js";
|
|
5
8
|
import { SETTINGS_FILE_ERRORS, SettingsFileError, applySettings, collectSettings, exportSettingsFile, parseSettingsFile, settingsFileName } from "../../../lib/settings/index.js";
|
|
6
9
|
import { JSON_FILE_TYPE, saveFile } from "../../../lib/rendering/screenshot/index.js";
|
|
7
10
|
import { css, html, nothing, unsafeCSS } from "lit";
|
|
@@ -12,11 +15,12 @@ var SETTINGS_FILE_ERROR_KEYS = {
|
|
|
12
15
|
[SETTINGS_FILE_ERRORS.read]: "paintCanvas.settings.fileReadFailed"
|
|
13
16
|
};
|
|
14
17
|
/**
|
|
15
|
-
*
|
|
18
|
+
* The user's app settings: a "Draw with the GPU" switch (the user's `ui.data.rendering`, used from the next start, so it
|
|
19
|
+
* says when the page needs reloading), and buttons: "Keyboard shortcuts", which opens a window to change them (see
|
|
16
20
|
* `pc-shortcut-settings`), and "Import settings" and "Export settings", which read and write a settings JSON file (input
|
|
17
|
-
* settings, keyboard shortcuts, colour palette, colours, theme and
|
|
18
|
-
* closes with its
|
|
19
|
-
* exporting fails.
|
|
21
|
+
* settings, keyboard shortcuts, colour palette, colours, profile graphs, theme, language and rendering). The window is a shaded
|
|
22
|
+
* `<pc-dialog-window>` over the whole page; it closes with its ⨉ button, Escape or a press outside it, and focus goes
|
|
23
|
+
* back to the button. Fires `pc-toast` after importing, or when importing or exporting fails.
|
|
20
24
|
*
|
|
21
25
|
* @example
|
|
22
26
|
* html`<pc-app-settings .app=${canvas}></pc-app-settings>`
|
|
@@ -43,37 +47,25 @@ var PcAppSettings = class extends PcElement {
|
|
|
43
47
|
font-family: var(--pc-font);
|
|
44
48
|
font-size: var(--pc-font-size);
|
|
45
49
|
}
|
|
50
|
+
/* One full-width button per row */
|
|
46
51
|
.actions {
|
|
47
52
|
display: flex;
|
|
48
|
-
flex-
|
|
53
|
+
flex-direction: column;
|
|
49
54
|
gap: var(--pc-space-2);
|
|
50
55
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
box-sizing: border-box;
|
|
54
|
-
width: min(480px, calc(100vw - 2 * var(--pc-space-3)));
|
|
55
|
-
max-height: calc(100vh - 2 * var(--pc-space-3));
|
|
56
|
-
padding: 0;
|
|
57
|
-
border: 0;
|
|
58
|
-
border-radius: var(--pc-radius);
|
|
59
|
-
background: var(--pc-surface-raised);
|
|
60
|
-
color: var(--pc-text);
|
|
61
|
-
box-shadow: var(--pc-shadow);
|
|
56
|
+
.actions button {
|
|
57
|
+
width: 100%;
|
|
62
58
|
}
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
.hint {
|
|
60
|
+
display: block;
|
|
61
|
+
color: var(--pc-text-muted);
|
|
62
|
+
font-size: 0.85em;
|
|
65
63
|
}
|
|
66
|
-
.
|
|
67
|
-
|
|
68
|
-
flex-direction: column;
|
|
69
|
-
gap: var(--pc-space-3);
|
|
70
|
-
box-shadow: none;
|
|
64
|
+
.pending {
|
|
65
|
+
color: var(--pc-text);
|
|
71
66
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
gap: var(--pc-space-2);
|
|
75
|
-
align-items: center;
|
|
76
|
-
justify-content: space-between;
|
|
67
|
+
pc-dialog-window {
|
|
68
|
+
--pc-dialog-width: 480px;
|
|
77
69
|
}
|
|
78
70
|
h2 {
|
|
79
71
|
margin: 0;
|
|
@@ -83,17 +75,11 @@ var PcAppSettings = class extends PcElement {
|
|
|
83
75
|
];
|
|
84
76
|
/** Saves exported files (replaceable for tests) */
|
|
85
77
|
saveFile = (blob, name) => saveFile(blob, name, void 0, JSON_FILE_TYPE);
|
|
78
|
+
changes = new ChangeController(this, () => [this.app?.ui]);
|
|
86
79
|
constructor() {
|
|
87
80
|
super();
|
|
88
81
|
this.shortcutsOpen = false;
|
|
89
82
|
}
|
|
90
|
-
updated(changed) {
|
|
91
|
-
if (!changed.has("shortcutsOpen")) return;
|
|
92
|
-
const dialog = this.renderRoot.querySelector("dialog");
|
|
93
|
-
if (!dialog) return;
|
|
94
|
-
if (this.shortcutsOpen && !dialog.open) dialog.showModal();
|
|
95
|
-
else if (!this.shortcutsOpen && dialog.open) dialog.close();
|
|
96
|
-
}
|
|
97
83
|
/** Close the keyboard shortcuts window */
|
|
98
84
|
closeShortcuts() {
|
|
99
85
|
this.shortcutsOpen = false;
|
|
@@ -143,39 +129,44 @@ var PcAppSettings = class extends PcElement {
|
|
|
143
129
|
kind: "error"
|
|
144
130
|
});
|
|
145
131
|
}
|
|
146
|
-
/** The keyboard shortcuts window
|
|
132
|
+
/** The keyboard shortcuts window, with its contents only while open */
|
|
147
133
|
renderShortcuts(app) {
|
|
148
|
-
return html`<dialog
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
134
|
+
return html`<pc-dialog-window
|
|
135
|
+
class="shortcuts-window"
|
|
136
|
+
shaded
|
|
137
|
+
?open=${this.shortcutsOpen}
|
|
138
|
+
@pc-dismiss=${() => this.closeShortcuts()}
|
|
139
|
+
>
|
|
140
|
+
<h2 slot="header-middle">${this.t("paintCanvas.shortcuts.title")}</h2>
|
|
141
|
+
${this.shortcutsOpen ? html`<pc-shortcut-settings
|
|
142
|
+
slot="body"
|
|
143
|
+
.settings=${app.shortcuts}
|
|
144
|
+
></pc-shortcut-settings>` : nothing}
|
|
145
|
+
</pc-dialog-window>`;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The switch that draws with the GPU (or the CPU) from the next start, saying when the page needs reloading to use
|
|
149
|
+
* the choice (see `PaintCanvas.rendering`).
|
|
150
|
+
*/
|
|
151
|
+
renderRendering(app) {
|
|
152
|
+
const chosen = app.ui.data.rendering;
|
|
153
|
+
const pending = chosen !== app.rendering;
|
|
154
|
+
return html`<pc-toggle-checkbox
|
|
155
|
+
class="gpu"
|
|
156
|
+
.checked=${chosen === "gpu"}
|
|
157
|
+
@change=${(e) => app.ui.update({ rendering: e.detail.checked ? "gpu" : "cpu" })}
|
|
154
158
|
>
|
|
155
|
-
${this.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
<button
|
|
161
|
-
type="button"
|
|
162
|
-
class="close dismiss"
|
|
163
|
-
autofocus
|
|
164
|
-
@click=${() => this.closeShortcuts()}
|
|
165
|
-
>
|
|
166
|
-
${this.t("paintCanvas.common.close")}
|
|
167
|
-
</button>
|
|
168
|
-
</div>
|
|
169
|
-
<pc-shortcut-settings
|
|
170
|
-
.settings=${app.shortcuts}
|
|
171
|
-
></pc-shortcut-settings>
|
|
172
|
-
</div>` : nothing}
|
|
173
|
-
</dialog>`;
|
|
159
|
+
${this.t("paintCanvas.settings.gpu")}
|
|
160
|
+
<span class="hint ${pending ? "pending" : ""}" aria-live="polite">
|
|
161
|
+
${this.t(pending ? "paintCanvas.settings.reloadToApply" : "paintCanvas.settings.gpuHint")}
|
|
162
|
+
</span>
|
|
163
|
+
</pc-toggle-checkbox>`;
|
|
174
164
|
}
|
|
175
165
|
render() {
|
|
176
166
|
const app = this.app;
|
|
177
167
|
if (!app) return nothing;
|
|
178
|
-
return html
|
|
168
|
+
return html`${this.renderRendering(app)}
|
|
169
|
+
<div class="actions">
|
|
179
170
|
<button
|
|
180
171
|
type="button"
|
|
181
172
|
class="pill shortcuts"
|