diff --git a/app/static/editor.js b/app/static/editor.js index 48c94f4..05b6e0d 100644 --- a/app/static/editor.js +++ b/app/static/editor.js @@ -120,6 +120,27 @@ function wrapCanvasText(text, maxWidthPx) { return lines.length ? lines : [""]; } +function textNaturalWidthMm(obj) { + const { value } = objectFont(obj); + ctx.save(); + ctx.font = value; + const lines = String(obj.text || " ").split("\n"); + const maxTextWidthPx = Math.max(...lines.map((line) => ctx.measureText(line || " ").width), 0); + ctx.restore(); + return Math.max(2, pxToMm(maxTextWidthPx) + 1); +} + +function autoFitTextObject(obj) { + if (!state.design.autoLength || obj.manualSize || (obj.type !== "text" && obj.type !== "symbol")) return; + const maxLength = state.design.orientation === "portrait" ? state.design.tapeWidthMm : 500; + const available = Math.max(2, maxLength - obj.x - state.design.marginMm); + obj.w = Math.min(available, textNaturalWidthMm(obj)); +} + +function autoFitTextObjects() { + for (const obj of state.design.objects) autoFitTextObject(obj); +} + function objectContentEndMm(obj) { if (obj.hidden) return 0; if (state.design.orientation === "portrait") return obj.y + obj.h; @@ -180,6 +201,7 @@ function syncDesignControls() { state.design.orientation = document.querySelector("input[name='orientation']:checked").value; controls.lengthMm.disabled = state.design.autoLength; if (state.design.autoLength) { + autoFitTextObjects(); state.design.lengthMm = contentLengthMm(); controls.lengthMm.value = state.design.lengthMm; } @@ -361,6 +383,7 @@ function addObject(type, data = {}) { cols: 2, ...data, }; + autoFitTextObject(base); state.design.objects.push(base); state.selectedId = base.id; draw(); @@ -401,11 +424,13 @@ function updateProps() { function applyProps() { const obj = selected(); if (!obj) return; + const manuallySizing = document.activeElement === controls.propW || document.activeElement === controls.propH; obj.text = controls.propText.value; obj.x = Number(controls.propX.value); obj.y = Number(controls.propY.value); obj.w = Number(controls.propW.value); obj.h = Number(controls.propH.value); + if (manuallySizing) obj.manualSize = true; obj.fontSizeMm = Number(controls.propFont.value); obj.lineMm = Number(controls.propLine.value); obj.align = controls.propAlign.value; @@ -413,6 +438,7 @@ function applyProps() { obj.fill = controls.propFill.checked; obj.rows = Number(controls.propRows.value); obj.cols = Number(controls.propCols.value); + autoFitTextObject(obj); draw(); } @@ -493,6 +519,7 @@ window.addEventListener("mousemove", (event) => { if (state.dragging.resize) { obj.w = Math.max(2, point.x - obj.x); obj.h = Math.max(2, point.y - obj.y); + obj.manualSize = true; } else { obj.x = Math.max(0, point.x - state.dragging.dx); obj.y = Math.max(0, point.y - state.dragging.dy);