001: /*
002: * Project: Gulden Utilies
003: * Class: de.gulden.util.text.TextTable
004: * Version: snapshot-beautyj-1.1
005: *
006: * Date: 2004-09-29
007: *
008: * This is a snapshot version of the Gulden Utilities,
009: * it is not released as a seperate version.
010: *
011: * Note: Contains auto-generated Javadoc comments created by BeautyJ.
012: *
013: * This is licensed under the GNU Lesser General Public License (LGPL)
014: * and comes with NO WARRANTY.
015: *
016: * Author: Jens Gulden
017: * Email: amoda@jensgulden.de
018: */
019:
020: package de.gulden.util.text;
021:
022: import de.gulden.util.Toolbox;
023: import java.util.*;
024: import java.util.Collection;
025:
026: /**
027: * Class TextTable.
028: *
029: * @author Jens Gulden
030: * @version snapshot-beautyj-1.1
031: */
032: public class TextTable {
033:
034: // ------------------------------------------------------------------------
035: // --- fields ---
036: // ------------------------------------------------------------------------
037:
038: /**
039: * The column count.
040: */
041: protected int columnCount;
042:
043: /**
044: * The rows.
045: */
046: protected Collection rows;
047:
048: /**
049: * The column weight array.
050: */
051: protected double[] columnWeight;
052:
053: /**
054: * The border.
055: */
056: protected boolean border;
057:
058: /**
059: * The borderchar.
060: */
061: protected char borderchar;
062:
063: /**
064: * The max width.
065: */
066: protected int maxWidth;
067:
068: // ------------------------------------------------------------------------
069: // --- constructors ---
070: // ------------------------------------------------------------------------
071:
072: /**
073: * Creates a new instance of TextTable.
074: */
075: public TextTable(int columnCount, int width) {
076: this (columnCount, width, initArray(columnCount), '+');
077: }
078:
079: /**
080: * Creates a new instance of TextTable.
081: */
082: public TextTable(int columnCount, int maxWidth,
083: double[] columnWeights, char borderchar) {
084: this .columnCount = columnCount;
085: this .maxWidth = maxWidth;
086: this .columnWeight = columnWeights;
087: this .borderchar = borderchar;
088: rows = new ArrayList();
089: }
090:
091: // ------------------------------------------------------------------------
092: // --- methods ---
093: // ------------------------------------------------------------------------
094:
095: /**
096: * Adds a row.
097: */
098: public void addRow(String[] row) {
099: rows.add(row);
100: }
101:
102: public String toString() {
103: // get all individual words
104: String[][][] tableWords = new String[rows.size()][columnCount][];
105: int row = 0;
106: for (Iterator it = rows.iterator(); it.hasNext();) {
107: String[] cols = (String[]) it.next();
108: for (int col = 0; col < columnCount; col++) {
109: String text = cols[col];
110: String[] words = splitWords(text);
111: tableWords[row][col] = words;
112: }
113: row++;
114: }
115: // get widths
116: int[] width = new int[columnCount];
117: int minW = 0;
118: for (int col = 0; col < columnCount; col++) {
119: width[col] = minimumWidth(tableWords, col);
120: minW += width[col];
121: }
122: minW += (columnCount + 1); // one space between each col
123: // can't help if minW>maxWidth, but if minW<maxWidth..:
124: int totalWidth;
125: if (minW < maxWidth) {
126: int rest = maxWidth - minW;
127: normalizeWeights();
128: totalWidth = 0;
129: for (int i = 0; i < columnCount; i++) {
130: width[i] += Math.round(((double) rest)
131: * columnWeight[i]);
132: totalWidth += width[i];
133: }
134: totalWidth += (columnCount + 1);
135: } else {
136: totalWidth = minW;
137: }
138:
139: // width[] now ok, create text boxes
140: String[][][] text = new String[rows.size()][columnCount][];
141: row = 0;
142: for (Iterator it = rows.iterator(); it.hasNext();) {
143: String[] r = (String[]) it.next();
144: for (int col = 0; col < columnCount; col++) {
145: String s = r[col];
146: text[row][col] = textBox(tableWords[row][col],
147: width[col]);
148: }
149: row++;
150: }
151: // output
152: StringBuffer out = new StringBuffer();
153: for (row = 0; row < text.length; row++) {
154: out.append(Toolbox.repeat(borderchar, totalWidth)
155: + Toolbox.NL); // horizontal border
156: int maxHeight = 0;
157: for (int col = 0; col < columnCount; col++) {
158: if (text[row][col].length > maxHeight) {
159: maxHeight = text[row][col].length;
160: }
161: }
162: for (int i = 0; i < maxHeight; i++) {
163: out.append(borderchar); // first vertical border
164: for (int col = 0; col < columnCount; col++) {
165: String t;
166: if (i < text[row][col].length) {
167: t = text[row][col][i];
168: } else {
169: t = Toolbox.repeat(" ", width[col]);
170: }
171: out.append(t + borderchar); // incl. vertical border
172: }
173: out.append(Toolbox.NL);
174: }
175: }
176: out.append(Toolbox.repeat(borderchar, totalWidth) + Toolbox.NL); // last horizontal border
177: return out.toString();
178: }
179:
180: private void normalizeWeights() {
181: double sum = 0.0;
182: for (int i = 0; i < columnCount; i++) {
183: sum += columnWeight[i];
184: }
185: if (sum != 0.0) {
186: for (int i = 0; i < columnCount; i++) {
187: columnWeight[i] /= sum;
188: }
189: }
190: // else special case: all weights 0 (means: keep table on minimum width possible)
191: }
192:
193: // ------------------------------------------------------------------------
194: // --- static methods ---
195: // ------------------------------------------------------------------------
196:
197: /**
198: * Inits the array.
199: */
200: private static double[] initArray(int size) {
201: double[] d = new double[size];
202: for (int i = 0; i < size; i++) {
203: d[i] = 1.0;
204: }
205: return d;
206: }
207:
208: private static int minimumWidth(String[][][] words, int column) {
209: int min = 0;
210: for (int row = 0; row < words.length; row++) {
211: String[] w = words[row][column];
212: for (int i = 0; i < w.length; i++) {
213: String s = w[i];
214: if (s.length() > min) {
215: min = s.length();
216: }
217: }
218: }
219: return min;
220: }
221:
222: private static String[] splitWords(String text) {
223: // returns line breaks as single words
224: Collection words = new ArrayList();
225: StringTokenizer st = new StringTokenizer(text, " \n", true);
226: while (st.hasMoreTokens()) {
227: String tok = st.nextToken();
228: if (!tok.equals(" ")) {
229: words.add(tok);
230: }
231: }
232: String[] r = new String[words.size()];
233: return (String[]) words.toArray(r);
234: }
235:
236: private static String[] textBox(String[] words, int width) {
237: Collection c = new ArrayList();
238: String line = "";
239: int i = 0;
240: boolean newline = false;
241: while (i < words.length) {
242: String word = words[i];
243: if (word.equals("\n")) {
244: newline = true;
245: i++;
246: } else {
247: // truncate if too long so that it would fit into a yet blank line
248: if (word.length() > width) {
249: word = word.substring(0, width);
250: }
251: boolean addSpace = (!line.equals(""))
252: && (!line.endsWith("-"));
253: if (addSpace) {
254: word = " " + word;
255: }
256: if ((line.length() + word.length()) <= width) {
257: line += word;
258: i++;
259: } else {
260: newline = true;
261: }
262: }
263: if (newline) {
264: line = Toolbox.padRight(line, " ", width);
265: c.add(line); // add code here to support center-aligned cells etc.
266: line = "";
267: newline = false;
268: }
269: }
270: if (!line.equals("")) {
271: line = Toolbox.padRight(line, " ", width);
272: c.add(line);
273: }
274: String[] s = new String[c.size()];
275: return (String[]) c.toArray(s);
276: }
277:
278: } // end TextTable
|