/*
* $Id: WordWrapper.java 535 2008-02-19 06:02:50Z weiju $
*
* Created on 2005/10/20
* Copyright 2005-2008 by Wei-ju Wu
* This file is part of The Z-machine Preservation Project (ZMPP).
*
* ZMPP is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZMPP is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZMPP. If not, see <http://www.gnu.org/licenses/>.
*/
package org.zmpp.swingui;
import java.awt.Font;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* A WordWrapper object lines out a given string using the specified algorithm.
* If buffered, whole words will be wrapped to the next line if too long,
* otherwise the strings will be written until the end of line is reachend and
* continued on the next one.
*
* @author Wei-ju Wu
* @version 1.0
*/
public class WordWrapper {
private Font font;
private Canvas canvas;
private int lineLength;
private boolean buffered;
public WordWrapper(int lineLength, Canvas canvas, Font font,
boolean isBuffered) {
this.lineLength = lineLength;
this.font = font;
this.buffered = isBuffered;
this.canvas = canvas;
}
public String[] wrap(int currentX, String input) {
// Do this if not empty
if (buffered) {
return wrapBuffered(currentX, input);
} else {
return wrapUnbuffered(currentX, input);
}
}
private String[] wrapBuffered(int currentX, String input) {
List<String> result = new ArrayList<String>();
StringTokenizer tok = new StringTokenizer(input, " \t\n\r", true);
String[] words = new String[tok.countTokens()];
int w = 0;
while (tok.hasMoreTokens()) {
words[w++] = tok.nextToken();
}
StringBuilder lineBuffer;
int currentWidth = currentX;
int wordWidth = 0;
int i = 0;
while (i < words.length) {
// Create the builder for a new line
lineBuffer = new StringBuilder();
for (; i < words.length; i++) {
wordWidth = canvas.getStringWidth(font, words[i]);
// Start a new line if a new line is found
if (words[i].charAt(0) == '\n') {
i++;
break;
}
if (currentWidth + wordWidth <= lineLength) {
// Append the current word if possible
lineBuffer.append(words[i]);
currentWidth += wordWidth;
} else {
// If a space lead to the line break, skip it
if (words[i].charAt(0) == ' ') {
i++;
}
// Next line
break;
}
}
lineBuffer.append('\n');
result.add(lineBuffer.toString());
currentWidth = 0;
}
// patch the last line if the string did not end with new line
if (input.charAt(input.length() - 1) != '\n') {
String lastline = result.get(result.size() - 1);
lastline = lastline.substring(0, lastline.length() - 1);
result.remove(result.size() - 1);
result.add(lastline);
}
return result.toArray(new String[0]);
}
private String[] wrapUnbuffered(int currentX, String input) {
List<String> result = new ArrayList<String>();
StringBuilder linebuffer = new StringBuilder();
int currentWidth = currentX;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
int charWidth = canvas.getCharWidth(font, c);
// new line
if ((currentWidth + charWidth > lineLength) || c == '\n') {
if (c == '\n') {
linebuffer.append('\n');
}
result.add(linebuffer.toString());
linebuffer = new StringBuilder();
currentWidth = 0;
}
if (c != '\n') {
linebuffer.append(c);
currentWidth += charWidth;
if (i == input.length() - 1) {
// last character in input, flush the buffer
result.add(linebuffer.toString());
}
}
}
//System.out.println("# lines: " + result.size());
return result.toArray(new String[0]);
}
}