Commit 1f590fce authored by Laureline Nevin's avatar Laureline Nevin ⌨️
Browse files

Implemented manual editing of export area values. Fixes #19

parent ab421df6
Loading
Loading
Loading
Loading
+33 −14
Changes for index.html: 33 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -96,20 +96,39 @@
            <label for="button-reset-controls" v-t="controls.reset"></label>
        </span>
        <div class="export-panel" v-show="phase === 'export'">
            <span>X: </span>
            <span>{{ Math.round(exportParams.area.x) }}</span>
            <span>Y: </span>
            <span>{{ Math.round(exportParams.area.y) }}</span>
            <span>Width: </span>
            <span>{{ Math.round(exportParams.area.w) }}</span>
            <span>Height: </span>
            <span>{{ Math.round(exportParams.area.h) }}</span>
            <span>Inner: </span>
            <span>{{ `${exportParams.innerGrab.round()}` }}</span>
            <span>Outer: </span>
            <span>{{ `${exportParams.outerGrab.round()}` }}</span>
            <span>Keys:</span>
            <span>{{ modKeys }}</span>
            <div class="export-area-matrix">
                <div></div>
                <div>Start</div>
                <div>Size</div>
                <div>End</div>
                <div>X</div>
                <div><input type="number" name="x-start" aria-label="X start" min="0" :max="totalSize[0]" step="1"
                            :value="exportParams.area.x" @change="fn.onExportParamInput"
                            :disabled="exportParams.lockedDim === 'start'"></div>
                <div><input type="number" name="x-size" aria-label="X size" min="0" :max="totalSize[0]" step="1"
                            :value="exportParams.area.w" @change="fn.onExportParamInput"
                            :disabled="exportParams.lockedDim === 'size'"></div>
                <div><input type="number" name="x-end" aria-label="X end" min="0" :max="totalSize[0]" step="1"
                            :value="exportParams.area.x2" @change="fn.onExportParamInput"
                            :disabled="exportParams.lockedDim === 'end'"></div>
                <div>Y</div>
                <div><input type="number" name="y-start" aria-label="Y start" min="0" :max="totalSize[1]" step="1"
                            :value="exportParams.area.y" @change="fn.onExportParamInput"
                            :disabled="exportParams.lockedDim === 'start'"></div>
                <div><input type="number" name="y-size" aria-label="Y size" min="0" :max="totalSize[1]" step="1"
                            :value="exportParams.area.h" @change="fn.onExportParamInput"
                            :disabled="exportParams.lockedDim === 'size'"></div>
                <div><input type="number" name="y-end" aria-label="Y end" min="0" :max="totalSize[1]" step="1"
                            :value="exportParams.area.y2" @change="fn.onExportParamInput"
                            :disabled="exportParams.lockedDim === 'end'"></div>
                <div></div>
                <div><label><input type="radio" name="lock-start" value="start"
                                   v-model="exportParams.lockedDim">🔒</label></div>
                <div><label><input type="radio" name="lock-size" value="size" v-model="exportParams.lockedDim">🔒</label>
                </div>
                <div><label><input type="radio" name="lock-end" value="end" v-model="exportParams.lockedDim">🔒</label>
                </div>
            </div>
            <span>Reset</span>
            <button v-icon="zoom-fit" @click="fn.setExportParams()"></button>
            <span>To view</span>
+52 −14
Changes for src/app.ts: 52 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ export class App {
                    this.onExportDialogClose,
                    this.downloadExportImage,
                    this.setExportParams,
                    this.onExportParamInput,
                ] as Array<(..._: any[]) => any>
            )
                .map((m) => [m.name, m.bind(this)] as const)
@@ -227,7 +228,6 @@ export class App {
            cursor: null as string | null,
            datasetsDisabled: false,
            dataset: '',
            modKeys: '',
            requestFullscreen: null as (() => void) | null,
            t: (k: string) => this.i18n.t(k),
            loc: this.getLocString.bind(this),
@@ -236,6 +236,7 @@ export class App {
            description: null as LocString | null,
            output: null as string | null,
            exportParams: App.DEFAULT_EXPORT_PARAMS,
            totalSize: [0, 0] as [number, number],
            pointerState: this.state.pointerState,
            raw: () => rx, // Function to un-proxify the rx object
        };
@@ -248,6 +249,7 @@ export class App {
            dezoom: 0,
            outerGrab: new Rect(0, 0, 0, 0),
            innerGrab: new Rect(0, 0, 0, 0),
            lockedDim: 'end',
        };
    }

@@ -370,6 +372,7 @@ export class App {
            this.rx.phase = 'render';
            this.requestRender();
            this.rx.description = value.dataset.description || null;
            this.rx.totalSize = value.totalSize;
        } else this.rx.description = null;
    }

@@ -700,23 +703,58 @@ export class App {
            let area = Rect.fromCorners(vec2.floor(tr, tr), vec2.ceil(bl, bl));
            area = area.intersection(canvas)!;
            let dezoom = Math.max(-source.zoomDepth, Math.min(0, Math.ceil(Math.log2(this.state.viewport.zoom))));
            this.rx.exportParams = {
                area,
                dezoom,
                outerGrab: area,
                innerGrab: area,
            };
            this.rx.exportParams.area = area;
            this.rx.exportParams.dezoom = dezoom;
        } else if (from === 'full') {
            this.rx.exportParams = {
                area: canvas,
                dezoom: 0,
                outerGrab: canvas,
                innerGrab: canvas,
            };
            this.rx.exportParams.area = canvas;
            this.rx.exportParams.dezoom = 0;
        } else throw new Error(`Unknown argument from = ${from}`);
        this.requestRender();
    }

    private onExportParamInput(ev: InputEvent) {
        if (this.rx.phase !== 'export') return;
        if (!(ev.currentTarget instanceof HTMLInputElement)) throw new Error();
        const val = ev.currentTarget.valueAsNumber;
        const area = this.rx.raw().exportParams.area,
            parts = ev.currentTarget.name.split('-'),
            ax = parts[0] === 'x' ? 0 : 1,
            start = area.xy,
            end = [area.x2, area.y2] as [number, number],
            total = this.rx.raw().totalSize,
            DIMS = ['start', 'size', 'end'],
            dim = DIMS.indexOf(parts[1]),
            lockDim = DIMS.indexOf(this.rx.exportParams.lockedDim);
        if (dim === -1 || lockDim === -1 || dim === lockDim) throw new Error();
        if (lockDim === 1) { // Computing size
            const size = area.wh[ax];
            if (dim === 0) { // Input start
                end[ax] = clamp(val + size, size, total[ax]);
                start[ax] = end[ax] - size;
            } else { // Input end
                start[ax] = clamp(val - size, 0, total[ax] - size);
                end[ax] = start[ax] + size;
            }
        } else if (dim === 1) { // Input size
            if (lockDim === 0) { // Computing end
                end[ax] = clamp(start[ax] + val, start[ax] + 1, total[ax]);
            } else { // Computing start
                start[ax] = clamp(end[ax] - val, 0, end[ax] - 1);
            }
        } else {
            if (dim === 0) { // Input start
                start[ax] = clamp(val, 0, total[ax] - 1);
                end[ax] = clamp(end[ax], start[ax] + 1, total[ax]);
            } else { // Input end
                end[ax] = clamp(val, 1, total[ax]);
                start[ax] = clamp(start[ax], 0, end[ax] - 1);
            }
        }
        const newArea = Rect.fromCorners(start, end);
        this.rx.exportParams.area = newArea;
        this.requestRender();
    }

    private exportImage() {
        const source = this.source;
        if (!source || !this.currentDataset || !this.maxCanvasSize) return;
@@ -910,7 +948,7 @@ export class App {

            let lightball = pointerState.dragging
                ? pointerState.overLightball
                : (ev.target as Element).id === 'ivoire-lightball';
                : (ev.target as Element)?.id === 'ivoire-lightball';
            const canvas = (lightball ? this.gls.lightball : this.gls.relight).canvas;
            const bb = canvas.getBoundingClientRect();
            const evpos = [ev.clientX - bb.x, ev.clientY - bb.y] as vec2;
+16 −3
Changes for src/style.sass: 16 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -142,10 +142,23 @@ body
			top: 0

	.export-panel
		.export-area-matrix
			width: 100%
			text-align: center
			display: grid
		grid-template-columns: auto 1fr
		grid-column-gap: 1rem
		justify-items: start
			grid-template-columns: auto 1fr 1fr 1fr
			grid-column-gap: .25rem
			align-items: baseline

			input[type=number]
				width: 100%
				margin: .25rem
				box-sizing: border-box
				appearance: textfield

				&:disabled
					background: silver
					color: black


.drop-shadow