001: package U2.P2;
002:
003: import java.util.*;
004:
005: /**
006: * Simple library for pretty printing text. A PP object represents
007: * <u>essentially</u> a list of strings. The method <u>render</u> can be used
008: * to render this object to a single string formatted in a certain
009: * way.
010: *
011: * <p>Logically the strings to be pretty printed are grouped
012: * hierarchically into groups that have to be printed side by side,
013: * and groups that have to be printed above the other.
014: *
015: *
016: * <p>In implementation PP is structured recursively. It has
017: * <u>right</u> and <u>under</u> pointers that again point to PP
018: * objects. The PP at 'right' is to be printed right to the current
019: * PP, and the PP at 'under' is to be printed below the current
020: * PP. There is also a field <u>line</u> which contains a single
021: * string (which should not contain a newline). It represents the
022: * single line of text belonging to the currect PP.
023: *
024: * <p>The field indent specifies an indentation offset for the PP (and
025: * all PP's below it).
026: *
027: * <p>In addition to the redering method, this library also provides
028: * some methods for constructing PPs.
029: *
030: * <p>Example: see source code.
031: *
032: * @author wishnu@cs.uu.nl
033: *
034: */
035: public class PP {
036:
037: /**
038: * Offset indentation for this PP.
039: */
040: private int indent = 0;
041:
042: /**
043: * A single line of string which is the content of this PP.
044: */
045: private String line = "";
046:
047: /**
048: * The PP to be printed right to this PP.
049: */
050: private PP right = null;
051:
052: /**
053: * The PP to be printed below this PP.
054: */
055: private PP under = null;
056:
057: /**
058: * Creating an empty PP.
059: */
060: public PP() {
061: }
062:
063: private String renderWorker(String output, int horOffset,
064: boolean aside) {
065:
066: if (indent < 0)
067: indent = 0; // ignore negative indentation
068: if (line != null) {
069: if (aside)
070: output = output + space(indent) + line;
071: else
072: output = output + space(horOffset + indent) + line;
073: }
074: if (right != null)
075: output = right.renderWorker(output, horOffset + indent
076: + line.length(), true);
077: if (under != null) {
078: output = output + "\n";
079: output = under.renderWorker(output, horOffset + indent,
080: false);
081: }
082: return output;
083: }
084:
085: /**
086: * To render this PP to a formatted string. The parameter is the
087: * initial indentation.
088: */
089: public String render(int horOffset) {
090: String output = "";
091: return renderWorker(output, horOffset, false);
092: }
093:
094: /**
095: * To make a PP containing a single line of string as its only content.
096: */
097: static public PP text(String s) {
098: PP pp = new PP();
099: pp.line = s;
100: return pp;
101: }
102:
103: private static String space(int n) {
104: String s = "";
105: for (; 0 < n; n--)
106: s = s + " ";
107: return s;
108: }
109:
110: /**
111: * Increase the indentation of the given PP with i.
112: */
113: public PP indent(int i) {
114: indent += i;
115: return this ;
116: }
117:
118: /**
119: * Set two PPs above each other.
120: */
121: public PP ontop(PP pp2) {
122: PP p = this ;
123: while (p.under != null)
124: p = p.under;
125: // now p is the botom-most element in pp1
126: p.under = pp2;
127: return this ;
128: }
129:
130: /**
131: * Set two PPs side by side.
132: */
133: public PP aside(PP pp2) {
134:
135: PP p = this ;
136: while (p.under != null)
137: p = p.under;
138: // now p is the botom-most element in pp1
139: while (p.right != null)
140: p = p.right;
141: // and now p is the botom-right most element in pp1
142: p.right = pp2;
143: return this ;
144: }
145:
146: /**
147: * As aside, but insert a space between.
148: *
149: * @see U2.P2.PP#aside
150: */
151: public PP aside_(PP pp2) {
152: aside(text(" ").aside(pp2));
153: return this ;
154: }
155:
156: /**
157: * Just for testing.
158: */
159: static public void main(String[] args) {
160:
161: PP pp = (text("Hello").aside_(text("Bob")
162: .ontop(
163: text("Alice").aside_(
164: text("Green").ontop(text("Grey"))))))
165: .ontop(text("Greeting from T2."));
166:
167: System.out.println(pp.render(5));
168:
169: }
170:
171: }
|