Before I re-invent the wheel (poorly), I'd like to know if there is a some existing Java code for wrapping text lines to a given maximum width. Ideally it would:
- respect existing linebreaks
- break up lines that exceed a maximum length on word boundaries
- break up words whose length exceeds the maximum line width by inserting hyphens
Edit: there are no "pixels" here, only java.lang.String. "maximum width" refers to the number of characters on a line.
Apache commons has WordUtils and wrap function in it:
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/text/WordUtils.html
Here's my take
private static final String linebreak = "\n"; // or "\r\n";
public static String wrap(String string, int lineLength) {
StringBuilder b = new StringBuilder();
for (String line : string.split(Pattern.quote(linebreak))) {
b.append(wrapLine(line, lineLength));
}
return b.toString();
}
private static String wrapLine(String line, int lineLength) {
if (line.length() == 0) return linebreak;
if (line.length() <= lineLength) return line + linebreak;
String[] words = line.split(" ");
StringBuilder allLines = new StringBuilder();
StringBuilder trimmedLine = new StringBuilder();
for (String word : words) {
if (trimmedLine.length() + 1 + word.length() <= lineLength) {
trimmedLine.append(word).append(" ");
} else {
allLines.append(trimmedLine).append(linebreak);
trimmedLine = new StringBuilder();
trimmedLine.append(word).append(" ");
}
}
if (trimmedLine.length() > 0) {
allLines.append(trimmedLine);
}
allLines.append(linebreak);
return allLines.toString();
}
(This solution strips two spaces to one space (so same fault that @jett has with Apache commons WordUtils)).
What you want to do would only work if you display the results with a fixed-width font. Otherwise the number of characters in a line would not be the same from line to line. If that is fine with you, I would say that your's is a fairly uncommon case (especially considering hyphenation), so I doubt you will find ready-made solutions.
If you're trying to format some manner of documentation, there's also the old unix roff (or runoff) family of commands. You'd just have to insert formatting commands and let roff do the heavy lifting.
public static List<String> stringBreak(String string, int maxChar) {
List<String> subLines = new ArrayList<String>();
int length = string.length();
int start = 0;
int end = maxChar;
if (length > maxChar) {
int noOfLines = (length / maxChar) + 1;
int endOfStr[] = new int[noOfLines];
for (int f = 0; f < noOfLines - 1; f++) {
int end1 = maxChar;
endOfStr[f] = end;
if (string.charAt(end - 1) != ' ') {
if (string.charAt(end - 2) == ' ') {
subLines.add(string.substring(start, end - 1));
start = end - 1;
end = end - 1 + end1;
} else if (string.charAt(end - 2) != ' '
&& string.charAt(end) == ' ') {
subLines.add(string.substring(start, end));
start = end;
end = end + end1;
} else if (string.charAt(end - 2) != ' ') {
subLines.add(string.substring(start, end) + "-");
start = end;
end = end + end1;
} else if (string.charAt(end + 2) == ' ') {
System.out.println("m here ............");
int lastSpaceIndex = string.substring(start, end)
.lastIndexOf("");
subLines.add(string.substring(start, lastSpaceIndex));
start = lastSpaceIndex;
end = lastSpaceIndex + end1;
}
} else {
subLines.add(string.substring(start, end));
start = end;
end = end + end1;
}
}
subLines.add(string.substring(endOfStr[noOfLines - 2], length));
}
return subLines;
}
Use the word-wrap library (available on Maven Central).
Here's one way to use it:
String text = "hello how are you going?";
String wrapped =
WordWrap.from(text)
.maxWidth(10)
.insertHyphens(true) // true is the default
.wrap();
Output is:
hi there
how are
you going?
The library conserves leading spaces on lines which is one complaint about the behaviour of the Apache commons-lang offering. You can also specify the stringWidth
function to get pixel-accurate results when rendering the text.
The library has decent unit test coverage (something to bear in mind when you consider copy and paste of code chunks from the web!).
The Maven dependency is:
<dependency>
<groupId>com.github.davidmoten</groupId>
<artifactId>word-wrap</artifactId>
<version>0.1.1</version>
</dependency>
Be sure to check for a later version.