/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package javax.microedition.lcdui;
import java.util.Vector;
/**
* Utility class used to wrap a string for StringItem layout.
*/
final class StringWrapper
{
private static final String DELIM_STR = " ,.;:!?-\n";
private StringWrapper()
{
super();
}
/**
* Method to be called by StringItemLayouter to provide correct wrapping of
* a single String to a Vector of strings.
*
* @param inputString Contents of a StringItem
* @param stringItemFont StringItem's font
* @param fullWidth Full width of the Form, in pixels
* @param freeWidth Free width is the current row of Form layout
* @return Vector of Strings, each element to be placed in one layout row
*/
static Vector wrapString(String inputString,
Font stringItemFont,
boolean leftToRightLayout,
int fullWidth,
int freeWidth)
{
if(leftToRightLayout)
{
// if left-to-right then just call wrapping method
return doWrapString(inputString, stringItemFont, fullWidth,
freeWidth);
}
else
{
// if right-to-left then:
// 1) reverse the string
// 2) do wrapping
// 3) reverse each vector element individually
StringBuffer temp = new StringBuffer(inputString);
Vector ret = doWrapString(temp.reverse().toString(),
stringItemFont, fullWidth, freeWidth);
for(int i = 0; i < ret.size(); i++)
{
temp.setLength(0);
temp.append((String) ret.elementAt(i));
ret.setElementAt(temp.reverse().toString(), i);
}
return ret;
}
}
/**
* Method to wrap a single string into many.
*
* @param inputString source string to wrap
* @param font source string's font
* @param fullWidth full form width in pixels
* @param freeWidth free width available in current layout row, in pixels
* @return Vector of Strings
*/
private static Vector doWrapString(String inputString,
Font font,
int fullWidth,
int freeWidth)
{
Vector result = new Vector();
// Could happen if StringItem.setText(null) or StringItem.setText("")
// was called
if(inputString == null)
{
result.addElement("");
return result;
}
int availableWidth = freeWidth;
int tokenWidth;
int nextDelimiterPos = -1;
int delimiterPos = 0;
String str = inputString;
String token = "";
while(str.length() > 0)
{
nextDelimiterPos = findNextDelimiter(str, nextDelimiterPos + 1);
token = str.substring(0, nextDelimiterPos).trim();
tokenWidth = font.stringWidth(token);
if(tokenWidth > availableWidth)
{
if(delimiterPos == 0)
{
// even the first word in the string is too long to fit
if((availableWidth < fullWidth)
&& (tokenWidth <= fullWidth))
{
// the long word would fit to the next full row
// result.addElement("");
availableWidth = fullWidth;
nextDelimiterPos = -1;
delimiterPos = 0;
continue;
}
if(tokenWidth > fullWidth)
{
// the long word does not fit to a full row
// do character-boundary wrapping
delimiterPos =
findWordBreak(token, font, availableWidth);
result.addElement(token.substring(0, delimiterPos));
str = str.substring(delimiterPos);
availableWidth = fullWidth;
nextDelimiterPos = -1;
delimiterPos = 0;
continue;
}
}
result.addElement(str.substring(0, delimiterPos).trim());
availableWidth = fullWidth;
str = str.substring(delimiterPos);
nextDelimiterPos = -1;
delimiterPos = 0;
continue;
}
if(nextDelimiterPos == str.length())
{
result.addElement(token);
availableWidth = fullWidth;
str = str.substring(nextDelimiterPos);
continue;
}
if(nextDelimiterPos < str.length()
&& str.charAt(nextDelimiterPos) == '\n')
{
result.addElement(token);
availableWidth = fullWidth;
str = str.substring(nextDelimiterPos + 1);
nextDelimiterPos = -1;
delimiterPos = 0;
continue;
}
delimiterPos = nextDelimiterPos;
}
return result;
}
/**
* Break a word on character border.
*
* @param word - Word to break
* @return Part of word that fits in the current available space
*/
private static int findWordBreak(String word, Font font, int width)
{
int breakPos = word.length();
while(font.substringWidth(word, 0, breakPos) > width)
{
breakPos--;
}
return breakPos;
}
/**
* The method searches for a delimiter in the String from beginning to end,
* starting from specified position.
*
* @param str String to search a delimiter
* @param startPos Start position for search
* @return The first delimiter found
*/
private static int findNextDelimiter(String str, int startPos)
{
int strLen = str.length();
int pos = startPos;
for(; pos < strLen; pos++)
{
int delimiter = DELIM_STR.indexOf(str.charAt(pos));
if(delimiter >= 0)
{
if(delimiter < 8)
{
// 8 is the '\n' character's index
return pos + 1;
}
break;
}
}
return pos;
}
}