Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.jdesktop.swingx.util.Utilities Maven / Gradle / Ivy
Go to download
A Maven project to aggregate all modules into a single artifact.
/*
* $Id$
*
* Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jdesktop.swingx.util;
import java.awt.Component;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
/**
* Contribution from NetBeans: Issue #319-swingx.
*
* PENDING: need to reconcile with OS, JVM... added as-is
* because needed the shortcut handling to fix #
*
* @author apple
*/
public class Utilities {
private Utilities() {
}
private static final int CTRL_WILDCARD_MASK = 32768;
private static final int ALT_WILDCARD_MASK = CTRL_WILDCARD_MASK * 2;
/** Operating system is Windows NT. */
public static final int OS_WINNT = 1 << 0;
/** Operating system is Windows 95. */
public static final int OS_WIN95 = OS_WINNT << 1;
/** Operating system is Windows 98. */
public static final int OS_WIN98 = OS_WIN95 << 1;
/** Operating system is Solaris. */
public static final int OS_SOLARIS = OS_WIN98 << 1;
/** Operating system is Linux. */
public static final int OS_LINUX = OS_SOLARIS << 1;
/** Operating system is HP-UX. */
public static final int OS_HP = OS_LINUX << 1;
/** Operating system is IBM AIX. */
public static final int OS_AIX = OS_HP << 1;
/** Operating system is SGI IRIX. */
public static final int OS_IRIX = OS_AIX << 1;
/** Operating system is Sun OS. */
public static final int OS_SUNOS = OS_IRIX << 1;
/** Operating system is Compaq TRU64 Unix */
public static final int OS_TRU64 = OS_SUNOS << 1;
/** Operating system is OS/2. */
public static final int OS_OS2 = OS_TRU64 << 2;
/** Operating system is Mac. */
public static final int OS_MAC = OS_OS2 << 1;
/** Operating system is Windows 2000. */
public static final int OS_WIN2000 = OS_MAC << 1;
/** Operating system is Compaq OpenVMS */
public static final int OS_VMS = OS_WIN2000 << 1;
/**
*Operating system is one of the Windows variants but we don't know which
*one it is
*/
public static final int OS_WIN_OTHER = OS_VMS << 1;
/** Operating system is unknown. */
public static final int OS_OTHER = OS_WIN_OTHER << 1;
/** Operating system is FreeBSD
* @since 4.50
*/
public static final int OS_FREEBSD = OS_OTHER << 1;
/** A mask for Windows platforms. */
public static final int OS_WINDOWS_MASK = OS_WINNT | OS_WIN95 | OS_WIN98 | OS_WIN2000 | OS_WIN_OTHER;
/** A mask for Unix platforms. */
public static final int OS_UNIX_MASK = OS_SOLARIS | OS_LINUX | OS_HP | OS_AIX | OS_IRIX | OS_SUNOS | OS_TRU64 |
OS_MAC | OS_FREEBSD;
/** A height of the windows's taskbar */
public static final int TYPICAL_WINDOWS_TASKBAR_HEIGHT = 27;
/** A height of the Mac OS X's menu */
private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24;
private static int operatingSystem = -1;
/** reference to map that maps allowed key names to their values (String, Integer)
and reference to map for mapping of values to their names */
private static Reference namesAndValues;
/** Get the operating system on which NetBeans is running.
* @return one of the OS_*
constants (such as {@link #OS_WINNT})
*/
public static int getOperatingSystem() {
if (operatingSystem == -1) {
String osName = System.getProperty("os.name");
if ("Windows NT".equals(osName)) { // NOI18N
operatingSystem = OS_WINNT;
} else if ("Windows 95".equals(osName)) { // NOI18N
operatingSystem = OS_WIN95;
} else if ("Windows 98".equals(osName)) { // NOI18N
operatingSystem = OS_WIN98;
} else if ("Windows 2000".equals(osName)) { // NOI18N
operatingSystem = OS_WIN2000;
} else if (osName.startsWith("Windows ")) { // NOI18N
operatingSystem = OS_WIN_OTHER;
} else if ("Solaris".equals(osName)) { // NOI18N
operatingSystem = OS_SOLARIS;
} else if (osName.startsWith("SunOS")) { // NOI18N
operatingSystem = OS_SOLARIS;
}
// JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick
else if (osName.endsWith("Linux")) { // NOI18N
operatingSystem = OS_LINUX;
} else if ("HP-UX".equals(osName)) { // NOI18N
operatingSystem = OS_HP;
} else if ("AIX".equals(osName)) { // NOI18N
operatingSystem = OS_AIX;
} else if ("Irix".equals(osName)) { // NOI18N
operatingSystem = OS_IRIX;
} else if ("SunOS".equals(osName)) { // NOI18N
operatingSystem = OS_SUNOS;
} else if ("Digital UNIX".equals(osName)) { // NOI18N
operatingSystem = OS_TRU64;
} else if ("OS/2".equals(osName)) { // NOI18N
operatingSystem = OS_OS2;
} else if ("OpenVMS".equals(osName)) { // NOI18N
operatingSystem = OS_VMS;
} else if (osName.equals("Mac OS X")) { // NOI18N
operatingSystem = OS_MAC;
} else if (osName.startsWith("Darwin")) { // NOI18N
operatingSystem = OS_MAC;
} else if (osName.toLowerCase(Locale.US).startsWith("freebsd")) { // NOI18N
operatingSystem = OS_FREEBSD;
} else {
operatingSystem = OS_OTHER;
}
}
return operatingSystem;
}
/** Test whether NetBeans is running on some variant of Windows.
* @return true
if Windows, false
if some other manner of operating system
*/
public static boolean isWindows() {
return (getOperatingSystem() & OS_WINDOWS_MASK) != 0;
}
/** Test whether NetBeans is running on some variant of Unix.
* Linux is included as well as the commercial vendors, and Mac OS X.
* @return true
some sort of Unix, false
if some other manner of operating system
*/
public static boolean isUnix() {
return (getOperatingSystem() & OS_UNIX_MASK) != 0;
}
/** Test whether the operating system supports icons on frames (windows).
* @return true
if it does not
*
*/
public static boolean isLargeFrameIcons() {
return (getOperatingSystem() == OS_SOLARIS) || (getOperatingSystem() == OS_HP);
}
/**
* Finds out the monitor where the user currently has the input focus.
* This method is usually used to help the client code to figure out on
* which monitor it should place newly created windows/frames/dialogs.
*
* @return the GraphicsConfiguration of the monitor which currently has the
* input focus
*/
private static GraphicsConfiguration getCurrentGraphicsConfiguration() {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner != null) {
Window w = SwingUtilities.getWindowAncestor(focusOwner);
if (w != null) {
return w.getGraphicsConfiguration();
}
}
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
/**
* Returns the usable area of the screen where applications can place its
* windows. The method subtracts from the screen the area of taskbars,
* system menus and the like. The screen this method applies to is the one
* which is considered current, ussually the one where the current input
* focus is.
*
* @return the rectangle of the screen where one can place windows
*
* @since 2.5
*/
public static Rectangle getUsableScreenBounds() {
return getUsableScreenBounds(getCurrentGraphicsConfiguration());
}
/**
* Returns the usable area of the screen where applications can place its
* windows. The method subtracts from the screen the area of taskbars,
* system menus and the like.
*
* @param gconf the GraphicsConfiguration of the monitor
* @return the rectangle of the screen where one can place windows
*
* @since 2.5
*/
public static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf) {
if (gconf == null) {
gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
Rectangle bounds = new Rectangle(gconf.getBounds());
String str;
str = System.getProperty("netbeans.screen.insets"); // NOI18N
if (str != null) {
StringTokenizer st = new StringTokenizer(str, ", "); // NOI18N
if (st.countTokens() == 4) {
try {
bounds.y = Integer.parseInt(st.nextToken());
bounds.x = Integer.parseInt(st.nextToken());
bounds.height -= (bounds.y + Integer.parseInt(st.nextToken()));
bounds.width -= (bounds.x + Integer.parseInt(st.nextToken()));
} catch (NumberFormatException ex) {
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
}
}
return bounds;
}
str = System.getProperty("netbeans.taskbar.height"); // NOI18N
if (str != null) {
bounds.height -= Integer.getInteger(str, 0).intValue();
return bounds;
}
try {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Insets insets = toolkit.getScreenInsets(gconf);
bounds.y += insets.top;
bounds.x += insets.left;
bounds.height -= (insets.top + insets.bottom);
bounds.width -= (insets.left + insets.right);
} catch (Exception ex) {
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
}
return bounds;
}
/** Initialization of the names and values
* @return array of two hashmaps first maps
* allowed key names to their values (String, Integer)
* and second
* hashtable for mapping of values to their names (Integer, String)
*/
private static synchronized HashMap[] initNameAndValues() {
if (namesAndValues != null) {
HashMap[] arr = (HashMap[]) namesAndValues.get();
if (arr != null) {
return arr;
}
}
Field[] fields;
// JW - fix Issue #353-swingx: play nicer inside sandbox.
try {
fields = KeyEvent.class.getDeclaredFields();
// fields = KeyEvent.class.getFields();
} catch (SecurityException e) {
// JW: need to do better? What are the use-cases where we don't have
// any access to the fields?
fields = new Field[0];
}
HashMap names = new HashMap(((fields.length * 4) / 3) + 5, 0.75f);
HashMap values = new HashMap(((fields.length * 4) / 3) + 5, 0.75f);
for (int i = 0; i < fields.length; i++) {
if (Modifier.isStatic(fields[i].getModifiers())) {
String name = fields[i].getName();
if (name.startsWith("VK_")) { // NOI18N
// exclude VK
name = name.substring(3);
try {
int numb = fields[i].getInt(null);
Integer value = new Integer(numb);
names.put(name, value);
values.put(value, name);
} catch (IllegalArgumentException ex) {
} catch (IllegalAccessException ex) {
}
}
}
}
if (names.get("CONTEXT_MENU") == null) { // NOI18N
Integer n = new Integer(0x20C);
names.put("CONTEXT_MENU", n); // NOI18N
values.put(n, "CONTEXT_MENU"); // NOI18N
n = new Integer(0x20D);
names.put("WINDOWS", n); // NOI18N
values.put(n, "WINDOWS"); // NOI18N
}
HashMap[] arr = { names, values };
namesAndValues = new SoftReference(arr);
return arr;
}
/** Converts a Swing key stroke descriptor to a familiar Emacs-like name.
* @param stroke key description
* @return name of the key (e.g. CS-F1
for control-shift-function key one)
* @see #stringToKey
*/
public static String keyToString(KeyStroke stroke) {
StringBuffer sb = new StringBuffer();
// add modifiers that must be pressed
if (addModifiers(sb, stroke.getModifiers())) {
sb.append('-');
}
HashMap[] namesAndValues = initNameAndValues();
String c = (String) namesAndValues[1].get(new Integer(stroke.getKeyCode()));
if (c == null) {
sb.append(stroke.getKeyChar());
} else {
sb.append(c);
}
return sb.toString();
}
/** Construct a new key description from a given universal string
* description.
* Provides mapping between Emacs-like textual key descriptions and the
* KeyStroke
object used in Swing.
*
* This format has following form:
*
[C][A][S][M]-identifier
*
Where:
*
* C
stands for the Control key
* A
stands for the Alt key
* S
stands for the Shift key
* M
stands for the Meta key
*
* The format also supports two wildcard codes, to support differences in
* platforms. These are the preferred choices for registering keystrokes,
* since platform conflicts will automatically be handled:
*
* D
stands for the default menu accelerator - the Control
* key on most platforms, the Command (meta) key on Macintosh
* O
stands for the alternate accelerator - the Alt key on
* most platforms, the Ctrl key on Macintosh (Macintosh uses Alt as a
* secondary shift key for composing international characters - if you bind
* Alt-8 to an action, a mac user with a French keyboard will not be able
* to type the [
character, which is a significant handicap
*
* If you use the wildcard characters, and specify a key which will conflict
* with keys the operating system consumes, it will be mapped to whichever
* choice can work - for example, on Macintosh, Command-Q is always consumed
* by the operating system, so D-Q
will always map to Control-Q.
*
* Every modifier before the hyphen must be pressed.
* identifier can be any text constant from {@link KeyEvent} but
* without the leading VK_
characters. So {@link KeyEvent#VK_ENTER} is described as
* ENTER
.
*
* @param s the string with the description of the key
* @return key description object, or null
if the string does not represent any valid key
*/
public static KeyStroke stringToKey(String s) {
StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), "-", true); // NOI18N
int needed = 0;
HashMap names = initNameAndValues()[0];
int lastModif = -1;
try {
for (;;) {
String el = st.nextToken();
// required key
if (el.equals("-")) { // NOI18N
if (lastModif != -1) {
needed |= lastModif;
lastModif = -1;
}
continue;
}
// if there is more elements
if (st.hasMoreElements()) {
// the text should describe modifiers
lastModif = readModifiers(el);
} else {
// last text must be the key code
Integer i = (Integer) names.get(el);
boolean wildcard = (needed & CTRL_WILDCARD_MASK) != 0;
//Strip out the explicit mask - KeyStroke won't know
//what to do with it
needed = needed & ~CTRL_WILDCARD_MASK;
boolean macAlt = (needed & ALT_WILDCARD_MASK) != 0;
needed = needed & ~ALT_WILDCARD_MASK;
if (i != null) {
//#26854 - Default accelerator should be Command on mac
if (wildcard) {
needed |= getMenuShortCutKeyMask();
if ((getOperatingSystem() & OS_MAC) != 0) {
if (!usableKeyOnMac(i.intValue(), needed)) {
needed &= ~getMenuShortCutKeyMask();
needed |= KeyEvent.CTRL_MASK;
}
}
}
if (macAlt) {
if (getOperatingSystem() == OS_MAC) {
needed |= KeyEvent.CTRL_MASK;
} else {
needed |= KeyEvent.ALT_MASK;
}
}
return KeyStroke.getKeyStroke(i.intValue(), needed);
} else {
return null;
}
}
}
} catch (NoSuchElementException ex) {
return null;
}
}
/**
* need to guard against headlessExceptions when testing.
* @return the acceletor mask for shortcuts.
*/
private static int getMenuShortCutKeyMask() {
if (GraphicsEnvironment.isHeadless()) {
return ((getOperatingSystem() & OS_MAC) != 0) ?
KeyEvent.META_MASK : KeyEvent.CTRL_MASK;
}
return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
}
private static boolean usableKeyOnMac(int key, int mask) {
//All permutations fail for Q except ctrl
if (key == KeyEvent.VK_Q) {
return false;
}
boolean isMeta = ((mask & KeyEvent.META_MASK) != 0) || ((mask & KeyEvent.CTRL_DOWN_MASK) != 0);
boolean isAlt = ((mask & KeyEvent.ALT_MASK) != 0) || ((mask & KeyEvent.ALT_DOWN_MASK) != 0);
boolean isOnlyMeta = isMeta && ((mask & ~(KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK)) == 0);
//Mac OS consumes keys Command+ these keys - the app will never see
//them, so CTRL should not be remapped for these
if (isOnlyMeta) {
return (key != KeyEvent.VK_H) && (key != KeyEvent.VK_SPACE) && (key != KeyEvent.VK_TAB);
} else return !((key == KeyEvent.VK_D) && isMeta && isAlt);
}
/** Convert a space-separated list of Emacs-like key binding names to a list of Swing key strokes.
* @param s the string with keys
* @return array of key strokes, or null
if the string description is not valid
* @see #stringToKey
*/
public static KeyStroke[] stringToKeys(String s) {
StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), " "); // NOI18N
ArrayList arr = new ArrayList();
while (st.hasMoreElements()) {
s = st.nextToken();
KeyStroke k = stringToKey(s);
if (k == null) {
return null;
}
arr.add(k);
}
return arr.toArray(new KeyStroke[arr.size()]);
}
/** Adds characters for modifiers to the buffer.
* @param buf buffer to add to
* @param modif modifiers to add (KeyEvent.XXX_MASK)
* @return true if something has been added
*/
private static boolean addModifiers(StringBuffer buf, int modif) {
boolean b = false;
if ((modif & KeyEvent.CTRL_MASK) != 0) {
buf.append("C"); // NOI18N
b = true;
}
if ((modif & KeyEvent.ALT_MASK) != 0) {
buf.append("A"); // NOI18N
b = true;
}
if ((modif & KeyEvent.SHIFT_MASK) != 0) {
buf.append("S"); // NOI18N
b = true;
}
if ((modif & KeyEvent.META_MASK) != 0) {
buf.append("M"); // NOI18N
b = true;
}
if ((modif & CTRL_WILDCARD_MASK) != 0) {
buf.append("D");
b = true;
}
if ((modif & ALT_WILDCARD_MASK) != 0) {
buf.append("O");
b = true;
}
return b;
}
/** Reads for modifiers and creates integer with required mask.
* @param s string with modifiers
* @return integer with mask
* @exception NoSuchElementException if some letter is not modifier
*/
private static int readModifiers(String s) throws NoSuchElementException {
int m = 0;
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case 'C':
m |= KeyEvent.CTRL_MASK;
break;
case 'A':
m |= KeyEvent.ALT_MASK;
break;
case 'M':
m |= KeyEvent.META_MASK;
break;
case 'S':
m |= KeyEvent.SHIFT_MASK;
break;
case 'D':
m |= CTRL_WILDCARD_MASK;
break;
case 'O':
m |= ALT_WILDCARD_MASK;
break;
default:
throw new NoSuchElementException(s);
}
}
return m;
}
/**
* Convert an array of objects to an array of primitive types.
* E.g. an Integer[]
would be changed to an int[]
.
* @param array the wrapper array
* @return a primitive array
* @throws IllegalArgumentException if the array element type is not a primitive wrapper
*/
public static Object toPrimitiveArray(Object[] array) {
if (array instanceof Integer[]) {
int[] r = new int[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Integer) array[i]).intValue();
return r;
}
if (array instanceof Boolean[]) {
boolean[] r = new boolean[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] != null) && ((Boolean) array[i]).booleanValue();
return r;
}
if (array instanceof Byte[]) {
byte[] r = new byte[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Byte) array[i]).byteValue();
return r;
}
if (array instanceof Character[]) {
char[] r = new char[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Character) array[i]).charValue();
return r;
}
if (array instanceof Double[]) {
double[] r = new double[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Double) array[i]).doubleValue();
return r;
}
if (array instanceof Float[]) {
float[] r = new float[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Float) array[i]).floatValue();
return r;
}
if (array instanceof Long[]) {
long[] r = new long[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Long) array[i]).longValue();
return r;
}
if (array instanceof Short[]) {
short[] r = new short[array.length];
int i;
int k = array.length;
for (i = 0; i < k; i++)
r[i] = (array[i] == null) ? 0 : ((Short) array[i]).shortValue();
return r;
}
throw new IllegalArgumentException();
}
/**
* Convert an array of primitive types to an array of objects.
* E.g. an int[]
would be turned into an Integer[]
.
* @param array the primitive array
* @return a wrapper array
* @throws IllegalArgumentException if the array element type is not primitive
*/
public static Object[] toObjectArray(Object array) {
if (array instanceof Object[]) {
return (Object[]) array;
}
if (array instanceof int[]) {
int i;
int k = ((int[]) array).length;
Integer[] r = new Integer[k];
for (i = 0; i < k; i++)
r[i] = new Integer(((int[]) array)[i]);
return r;
}
if (array instanceof boolean[]) {
int i;
int k = ((boolean[]) array).length;
Boolean[] r = new Boolean[k];
for (i = 0; i < k; i++)
r[i] = ((boolean[]) array)[i] ? Boolean.TRUE : Boolean.FALSE;
return r;
}
if (array instanceof byte[]) {
int i;
int k = ((byte[]) array).length;
Byte[] r = new Byte[k];
for (i = 0; i < k; i++)
r[i] = new Byte(((byte[]) array)[i]);
return r;
}
if (array instanceof char[]) {
int i;
int k = ((char[]) array).length;
Character[] r = new Character[k];
for (i = 0; i < k; i++)
r[i] = new Character(((char[]) array)[i]);
return r;
}
if (array instanceof double[]) {
int i;
int k = ((double[]) array).length;
Double[] r = new Double[k];
for (i = 0; i < k; i++)
r[i] = new Double(((double[]) array)[i]);
return r;
}
if (array instanceof float[]) {
int i;
int k = ((float[]) array).length;
Float[] r = new Float[k];
for (i = 0; i < k; i++)
r[i] = new Float(((float[]) array)[i]);
return r;
}
if (array instanceof long[]) {
int i;
int k = ((long[]) array).length;
Long[] r = new Long[k];
for (i = 0; i < k; i++)
r[i] = new Long(((long[]) array)[i]);
return r;
}
if (array instanceof short[]) {
int i;
int k = ((short[]) array).length;
Short[] r = new Short[k];
for (i = 0; i < k; i++)
r[i] = new Short(((short[]) array)[i]);
return r;
}
throw new IllegalArgumentException();
}
/** Wrap multi-line strings (and get the individual lines).
* @param original the original string to wrap
* @param width the maximum width of lines
* @param breakIterator breaks original to chars, words, sentences, depending on what instance you provide.
* @param removeNewLines if true
, any newlines in the original string are ignored
* @return the lines after wrapping
*/
public static String[] wrapStringToArray(
String original, int width, BreakIterator breakIterator, boolean removeNewLines
) {
if (original.length() == 0) {
return new String[] { original };
}
String[] workingSet;
// substitute original newlines with spaces,
// remove newlines from head and tail
if (removeNewLines) {
original = trimString(original);
original = original.replace('\n', ' ');
workingSet = new String[] { original };
} else {
StringTokenizer tokens = new StringTokenizer(original, "\n"); // NOI18N
int len = tokens.countTokens();
workingSet = new String[len];
for (int i = 0; i < len; i++) {
workingSet[i] = tokens.nextToken();
}
}
if (width < 1) {
width = 1;
}
if (original.length() <= width) {
return workingSet;
}
widthcheck: {
boolean ok = true;
for (int i = 0; i < workingSet.length; i++) {
ok = ok && (workingSet[i].length() < width);
if (!ok) {
break widthcheck;
}
}
return workingSet;
}
java.util.ArrayList lines = new java.util.ArrayList();
int lineStart = 0; // the position of start of currently processed line in the original string
for (int i = 0; i < workingSet.length; i++) {
if (workingSet[i].length() < width) {
lines.add(workingSet[i]);
} else {
breakIterator.setText(workingSet[i]);
int nextStart = breakIterator.next();
int prevStart = 0;
do {
while (((nextStart - lineStart) < width) && (nextStart != BreakIterator.DONE)) {
prevStart = nextStart;
nextStart = breakIterator.next();
}
if (nextStart == BreakIterator.DONE) {
nextStart = prevStart = workingSet[i].length();
}
if (prevStart == 0) {
prevStart = nextStart;
}
lines.add(workingSet[i].substring(lineStart, prevStart));
lineStart = prevStart;
prevStart = 0;
} while (lineStart < workingSet[i].length());
lineStart = 0;
}
}
String[] s = new String[lines.size()];
return (String[]) lines.toArray(s);
}
private static String trimString(String s) {
int idx = 0;
char c;
final int slen = s.length();
if (slen == 0) {
return s;
}
do {
c = s.charAt(idx++);
} while (((c == '\n') || (c == '\r')) && (idx < slen));
s = s.substring(--idx);
idx = s.length() - 1;
if (idx < 0) {
return s;
}
do {
c = s.charAt(idx--);
} while (((c == '\n') || (c == '\r')) && (idx >= 0));
return s.substring(0, idx + 2);
}
}