diff --git a/src/main/java/edu/unl/cse/bohn/StringBox.java b/src/main/java/edu/unl/cse/bohn/StringBox.java index d0d3d2849b12020425a351b744db04278c547f33..820441e62948e3c3ea892125f2bcc29531ea0c62 100644 --- a/src/main/java/edu/unl/cse/bohn/StringBox.java +++ b/src/main/java/edu/unl/cse/bohn/StringBox.java @@ -23,6 +23,16 @@ package edu.unl.cse.bohn; * <p>Note that StringBox is <i>not</i> robust to hidden characters, such as VT100 escape sequences.</p> */ public class StringBox { + /** + * Horizontal alignment directives + */ + public enum Horizontal {LEFT, RIGHT} + + /** + * Vertical alignment directives + */ + public enum Vertical {TOP, BOTTOM} + private int maximumWidth; private int maximumHeight; private int logicalHeight; @@ -89,9 +99,59 @@ public class StringBox { * @see #placeStringAlignTopLeft(String, int, int) */ public StringBox placeString(String string, int topRow, int leftColumn) { - return placeStringAlignTopLeft(string, topRow, leftColumn); + return placeString(string, Vertical.TOP, topRow, Horizontal.LEFT, leftColumn); + } + + /** + * <p>Places a string in the StringBox. If <code>verticalAlignment</code> is <code>TOP</code> then the string's + * first line will be in the <code>verticalPosition</code>'th row, and each subsequent line will be in each + * subsequent row. If <code>verticalAlignment</code> is <code>BOTTOM</code> then the string's last line will be in + * the <code>verticalPosition</code>'th row, and each preceding line will be in each preceding row. If + * <code>horizontalAlignment</code> is <code>LEFT</code> then each line will be left-justified to the + * <code>horizontalPosition</code>'th column. If <code>horizontalAlignment</code> is <code>RIGHT</code> then each + * line will be right-justified to the <code>horizontalPosition</code>'th column.</p> + * + * @param string the string to be placed in the StringBox + * @param verticalAlignment vertical alignment directive (top/bottom) + * @param verticalPosition the row on which the string should be top/bottom aligned + * @param horizontalAlignment horizontal alignment directive (left/right) + * @param horizontalPosition the column on which the string should be top/bottom aligned + * @return the current StringBox object, suitable for chained calls + */ + public StringBox placeString(String string, Vertical verticalAlignment, int verticalPosition, + Horizontal horizontalAlignment, int horizontalPosition) { + String[] strings = string.split(System.lineSeparator()); + // This would benefit from the switch expression in JDK 12/13 + int topRow = verticalAlignment == Vertical.TOP ? verticalPosition : + verticalAlignment == Vertical.BOTTOM ? verticalPosition - strings.length + 1 : + 0; + int firstRow = Math.max(topRow, 0); + int lastRow = Math.min(topRow + strings.length, maximumHeight); + int offset = -topRow; + for (int i = firstRow; i < lastRow; i++) { + switch (horizontalAlignment) { + case LEFT: + rows[i].placeSubstringAlignLeft(strings[i + offset], horizontalPosition); + break; + case RIGHT: + rows[i].placeSubstringAlignRight(strings[i + offset], horizontalPosition); + break; + default: + System.err.println("Unreachable code was reached in StringBox.placeString()!"); + System.err.println("\thorizontalAlignment == " + horizontalAlignment); + Horizontal recoveryAlignment = Horizontal.LEFT; + System.err.println("\tAttempting to recover with horizontalAlignment = " + recoveryAlignment); + rows[i].placeSubstringAlignLeft(strings[i + offset], horizontalPosition); + } + } + logicalHeight = Math.max(logicalHeight, lastRow); + return this; } + /* ****************** + * LEGACY METHODS * + ********************/ + /** * Places a string in the StringBox with its upper-left corner in the specified location. If the string * contains multiple lines, each line after the first will be placed in the row subsequent to the previous line, @@ -104,15 +164,7 @@ public class StringBox { * @return the current StringBox object, suitable for chained calls */ public StringBox placeStringAlignTopLeft(String string, int topRow, int leftColumn) { - String[] strings = string.split("\n"); - int firstRow = Math.max(topRow, 0); - int lastRow = Math.min(topRow + strings.length, maximumHeight); - int offset = -topRow; - for (int i = firstRow; i < lastRow; i++) { - rows[i].placeSubstringAlignLeft(strings[i + offset], leftColumn); - } - logicalHeight = Math.max(logicalHeight, lastRow); - return this; + return placeString(string, Vertical.TOP, topRow, Horizontal.LEFT, leftColumn); } /** @@ -127,8 +179,7 @@ public class StringBox { * @return the current StringBox object, suitable for chained calls */ public StringBox placeStringAlignBottomLeft(String string, int bottomRow, int leftColumn) { - String[] strings = string.split("\n"); - return placeStringAlignTopLeft(string, bottomRow - strings.length + 1, leftColumn); + return placeString(string, Vertical.BOTTOM, bottomRow, Horizontal.LEFT, leftColumn); } /** @@ -143,15 +194,7 @@ public class StringBox { * @return the current StringBox object, suitable for chained calls */ public StringBox placeStringAlignTopRight(String string, int topRow, int rightColumn) { - String[] strings = string.split("\n"); - int firstRow = Math.max(topRow, 0); - int lastRow = Math.min(topRow + strings.length, maximumHeight); - int offset = -topRow; - for (int i = firstRow; i < lastRow; i++) { - rows[i].placeSubstringAlignRight(strings[i + offset], rightColumn); - } - logicalHeight = Math.max(logicalHeight, lastRow); - return this; + return placeString(string, Vertical.TOP, topRow, Horizontal.RIGHT, rightColumn); } /** @@ -166,10 +209,13 @@ public class StringBox { * @return the current StringBox object, suitable for chained calls */ public StringBox placeStringAlignBottomRight(String string, int bottomRow, int rightColumn) { - String[] strings = string.split("\n"); - return placeStringAlignTopRight(string, bottomRow - strings.length + 1, rightColumn); + return placeString(string, Vertical.BOTTOM, bottomRow, Horizontal.RIGHT, rightColumn); } + /* ************************* + * END OF LEGACY METHODS * + ***************************/ + /** * <p>Generates the string that the client code produced by calling {@link #placeString(String, int, int)} and * its related methods. Any unused lines between the last line of text and the bottom of the StringBox will be @@ -201,11 +247,11 @@ public class StringBox { returnString.append(rows[0].toString()); } for (int i = 1; i < logicalHeight; i++) { - returnString.append("\n").append(rows[i].toString()); + returnString.append(System.lineSeparator()).append(rows[i].toString()); } if (padToHeight) { for (int i = logicalHeight; i < maximumHeight; i++) { - returnString.append("\n").append(rows[i].toString()); + returnString.append(System.lineSeparator()).append(rows[i].toString()); } } return returnString.toString();