From 2eb9266c3044426371257a0010824d795a7bc0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Hatcher?= Date: Sat, 7 Jun 2025 00:00:48 +0200 Subject: [PATCH] UPDATE: Factor out a couple of helper functions from the main canvas file --- .../src/components/WorksheetCanvas/util.ts | 63 +++++++++++++++++++ .../WorksheetCanvas/worksheetCanvas.ts | 2 + 2 files changed, 65 insertions(+) create mode 100644 webapp/IronCalc/src/components/WorksheetCanvas/util.ts diff --git a/webapp/IronCalc/src/components/WorksheetCanvas/util.ts b/webapp/IronCalc/src/components/WorksheetCanvas/util.ts new file mode 100644 index 0000000..56a5a8d --- /dev/null +++ b/webapp/IronCalc/src/components/WorksheetCanvas/util.ts @@ -0,0 +1,63 @@ +// Get a 10% transparency of an hex color +export function hexToRGBA10Percent(colorHex: string): string { + // Remove the leading hash (#) if present + const hex = colorHex.replace(/^#/, ""); + + // Parse the hex color + const red = Number.parseInt(hex.substring(0, 2), 16); + const green = Number.parseInt(hex.substring(2, 4), 16); + const blue = Number.parseInt(hex.substring(4, 6), 16); + + // Set the alpha (opacity) to 0.1 (10%) + const alpha = 0.1; + + // Return the RGBA color string + return `rgba(${red}, ${green}, ${blue}, ${alpha})`; +} + +/** + * Splits the given text into multiple lines. If `wrapText` is true, it applies word-wrapping + * based on the specified canvas context, maximum width, and horizontal padding. + * + * - First, the text is split by newline characters so that explicit newlines are respected. + * - If wrapping is enabled, each line is further split into words and measured against the + * available width. Whenever adding an extra word would exceed + * this limit, a new line is started. + * + * @param text The text to split into lines. + * @param wrapText Whether to apply word-wrapping or just return text split by newlines. + * @param context The `CanvasRenderingContext2D` used for measuring text width. + * @param width The maximum width for each line. + * @returns An array of lines (strings), each fitting within the specified width if wrapping is enabled. + */ +export function computeWrappedLines( + text: string, + wrapText: boolean, + context: CanvasRenderingContext2D, + width: number, +): string[] { + // Split the text into lines + const rawLines = text.split("\n"); + if (!wrapText) { + // If there is no wrapping, return the raw lines + return rawLines; + } + const wrappedLines = []; + for (const line of rawLines) { + const words = line.split(" "); + let currentLine = words[0]; + for (let i = 1; i < words.length; i += 1) { + const word = words[i]; + const testLine = `${currentLine} ${word}`; + const textWidth = context.measureText(testLine).width; + if (textWidth < width) { + currentLine = testLine; + } else { + wrappedLines.push(currentLine); + currentLine = word; + } + } + wrappedLines.push(currentLine); + } + return wrappedLines; +} diff --git a/webapp/IronCalc/src/components/WorksheetCanvas/worksheetCanvas.ts b/webapp/IronCalc/src/components/WorksheetCanvas/worksheetCanvas.ts index 5a4ea4b..cda2da9 100644 --- a/webapp/IronCalc/src/components/WorksheetCanvas/worksheetCanvas.ts +++ b/webapp/IronCalc/src/components/WorksheetCanvas/worksheetCanvas.ts @@ -18,6 +18,8 @@ import { headerTextColor, outlineColor, } from "./constants"; +import { attachOutlineHandle } from "./outlineHandle"; +import { computeWrappedLines, hexToRGBA10Percent } from "./util"; export interface CanvasSettings { model: Model;