/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.scenegraph.utils; import java.awt.FontMetrics; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; public final class TextUtil { /** * @param text * @param g * @param bounds * @return */ public static String[] wordWrap(String text, FontMetrics metrics, int maxLineWidth) { Collection result = new ArrayList(); int[] whitespacePos = new int[8]; int whitespaceTop = 0; int pos = 0; int length = text.length(); int cumulatedLineWidth = 0; int dotWidth = metrics.charWidth('.'); int dot3Width = 3*dotWidth; boolean nonWhitespaceFound = false; out: while (pos < length) { char c = text.charAt(pos); int cWidth = metrics.charWidth(c); if (Character.isWhitespace(c)) { if (nonWhitespaceFound) { if (whitespacePos.length <= whitespaceTop) whitespacePos = Arrays.copyOf(whitespacePos, whitespacePos.length*2); whitespacePos[whitespaceTop++] = pos; } } else { nonWhitespaceFound = true; } // System.out.println("cumulated: " + cumulatedLineWidth); // System.out.println(" width: " + cWidth); // System.out.println(" max: " + maxLineWidth); if (cumulatedLineWidth + cWidth > maxLineWidth) { // System.out.println("overran line: " + (result.size() + 1) + ": '" + text.substring(0, pos) + "'"); // Look for last whitespace position to cut at int nextLineStartPos = -1; if (whitespaceTop > 0) { int cutPos = whitespacePos[--whitespaceTop]; result.add(text.substring(0, cutPos)); nextLineStartPos = cutPos + 1; } else { // No whitespace available, just cut the string and insert "..." at the end. int rollbackWidth = cumulatedLineWidth + dot3Width; int rollbackPos = pos; while (rollbackPos > 0 && rollbackWidth > maxLineWidth) { rollbackWidth -= metrics.charWidth(text.charAt(--rollbackPos)); } // Cannot word wrap a single character anything into the specified max width. if (rollbackPos == 0) { result.add(text); break out; } result.add(text.substring(0, rollbackPos) + "..."); // Search for next whitespace in the text after pos and start the next line from there. int nextWhitespacePos = pos; for (;nextWhitespacePos < length && !Character.isWhitespace(text.charAt(nextWhitespacePos)); ++nextWhitespacePos); nextLineStartPos = nextWhitespacePos < length ? nextWhitespacePos + 1 : nextWhitespacePos; } text = text.substring(nextLineStartPos); length = text.length(); pos = 0; cumulatedLineWidth = 0; nonWhitespaceFound = false; whitespaceTop = 0; continue; } cumulatedLineWidth += cWidth; ++pos; } if (text.length() > 0) result.add(text); return result.toArray(new String[result.size()]); } }