/**
* Jexer - Java Text User Interface
*
- * Version: $Id$
- *
- * Author: Kevin Lamonte, <a href="mailto:kevin.lamonte@gmail.com">kevin.lamonte@gmail.com</a>
- *
* License: LGPLv3 or later
*
- * Copyright: This module is licensed under the GNU Lesser General
- * Public License Version 3. Please see the file "COPYING" in this
- * directory for more information about the GNU Lesser General Public
- * License Version 3.
+ * This module is licensed under the GNU Lesser General Public License
+ * Version 3. Please see the file "COPYING" in this directory for more
+ * information about the GNU Lesser General Public License Version 3.
*
* Copyright (C) 2015 Kevin Lamonte
*
* http://www.gnu.org/licenses/, or write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
*/
package jexer.io;
public abstract class Screen {
/**
- * Emit debugging to stderr
+ * Width of the visible window.
*/
- public boolean debugToStderr;
+ protected int width;
/**
- * Width of the visible window
+ * Height of the visible window.
*/
- protected int width;
+ protected int height;
/**
- * Height of the visible window
+ * Drawing offset for x.
*/
- protected int height;
+ private int offsetX;
+
+ /**
+ * Set drawing offset for x.
+ *
+ * @param offsetX new drawing offset
+ */
+ public final void setOffsetX(final int offsetX) {
+ this.offsetX = offsetX;
+ }
+
+ /**
+ * Drawing offset for y.
+ */
+ private int offsetY;
+
+ /**
+ * Set drawing offset for y.
+ *
+ * @param offsetY new drawing offset
+ */
+ public final void setOffsetY(final int offsetY) {
+ this.offsetY = offsetY;
+ }
+
+ /**
+ * Ignore anything drawn right of clipRight.
+ */
+ private int clipRight;
+
+ /**
+ * Get right drawing clipping boundary.
+ *
+ * @return drawing boundary
+ */
+ public final int getClipRight() {
+ return clipRight;
+ }
+
+ /**
+ * Set right drawing clipping boundary.
+ *
+ * @param clipRight new boundary
+ */
+ public final void setClipRight(final int clipRight) {
+ this.clipRight = clipRight;
+ }
/**
- * Drawing offset for x
+ * Ignore anything drawn below clipBottom.
*/
- public int offsetX;
+ private int clipBottom;
/**
- * Drawing offset for y
+ * Get bottom drawing clipping boundary.
+ *
+ * @return drawing boundary
*/
- public int offsetY;
+ public final int getClipBottom() {
+ return clipBottom;
+ }
/**
- * Ignore anything drawn right of clipRight
+ * Set bottom drawing clipping boundary.
+ *
+ * @param clipBottom new boundary
*/
- public int clipRight;
+ public final void setClipBottom(final int clipBottom) {
+ this.clipBottom = clipBottom;
+ }
/**
- * Ignore anything drawn below clipBottom
+ * Ignore anything drawn left of clipLeft.
*/
- public int clipBottom;
+ private int clipLeft;
/**
- * Ignore anything drawn left of clipLeft
+ * Get left drawing clipping boundary.
+ *
+ * @return drawing boundary
*/
- public int clipLeft;
+ public final int getClipLeft() {
+ return clipLeft;
+ }
/**
- * Ignore anything drawn above clipTop
+ * Set left drawing clipping boundary.
+ *
+ * @param clipLeft new boundary
*/
- public int clipTop;
+ public final void setClipLeft(final int clipLeft) {
+ this.clipLeft = clipLeft;
+ }
/**
- * The physical screen last sent out on flush()
+ * Ignore anything drawn above clipTop.
+ */
+ private int clipTop;
+
+ /**
+ * Get top drawing clipping boundary.
+ *
+ * @return drawing boundary
+ */
+ public final int getClipTop() {
+ return clipTop;
+ }
+
+ /**
+ * Set top drawing clipping boundary.
+ *
+ * @param clipTop new boundary
+ */
+ public final void setClipTop(final int clipTop) {
+ this.clipTop = clipTop;
+ }
+
+ /**
+ * The physical screen last sent out on flush().
*/
protected Cell [][] physical;
/**
- * The logical screen being rendered to
+ * The logical screen being rendered to.
*/
protected Cell [][] logical;
/**
- * When true, logical != physical
+ * When true, logical != physical.
+ */
+ protected volatile boolean dirty;
+
+ /**
+ * Get dirty flag.
+ *
+ * @return if true, the logical screen is not in sync with the physical
+ * screen
*/
- public boolean dirty;
+ public final boolean isDirty() {
+ return dirty;
+ }
/**
* Set if the user explicitly wants to redraw everything starting with a
- * ECMATerminal.clearAll()
+ * ECMATerminal.clearAll().
*/
protected boolean reallyCleared;
/**
* If true, the cursor is visible and should be placed onscreen at
- * (cursorX, cursorY) during a call to flushPhysical()
+ * (cursorX, cursorY) during a call to flushPhysical().
*/
protected boolean cursorVisible;
/**
- * Cursor X position if visible
+ * Cursor X position if visible.
*/
protected int cursorX;
/**
- * Cursor Y position if visible
+ * Cursor Y position if visible.
*/
protected int cursorY;
* @param y row coordinate. 0 is the top-most row.
* @return attributes at (x, y)
*/
- public CellAttributes getAttrXY(int x, int y) {
- CellAttributes attr = new CellAttributes();
- attr.setTo(logical[x][y]);
- return attr;
+ public final CellAttributes getAttrXY(final int x, final int y) {
+ CellAttributes attr = new CellAttributes();
+ if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+ attr.setTo(logical[x][y]);
+ }
+ return attr;
}
/**
* @param y row coordinate. 0 is the top-most row.
* @param attr attributes to use (bold, foreColor, backColor)
*/
- public void putAttrXY(int x, int y, CellAttributes attr) {
- putAttrXY(x, y, attr, true);
+ public final void putAttrXY(final int x, final int y,
+ final CellAttributes attr) {
+
+ putAttrXY(x, y, attr, true);
}
-
+
/**
* Set the attributes at one location.
*
* @param attr attributes to use (bold, foreColor, backColor)
* @param clip if true, honor clipping/offset
*/
- public void putAttrXY(int x, int y, CellAttributes attr, boolean clip) {
-
- int X = x;
- int Y = y;
-
- if (clip) {
- if ((x < clipLeft) || (x >= clipRight) ||
- (y < clipTop) || (y >= clipBottom)) {
- return;
- }
- X += offsetX;
- Y += offsetY;
- }
-
- if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
- dirty = true;
- logical[X][Y].foreColor = attr.foreColor;
- logical[X][Y].backColor = attr.backColor;
- logical[X][Y].bold = attr.bold;
- logical[X][Y].blink = attr.blink;
- logical[X][Y].reverse = attr.reverse;
- logical[X][Y].underline = attr.underline;
- logical[X][Y].protect = attr.protect;
- }
+ public final void putAttrXY(final int x, final int y
+ , final CellAttributes attr, final boolean clip) {
+
+ int X = x;
+ int Y = y;
+
+ if (clip) {
+ if ((x < clipLeft)
+ || (x >= clipRight)
+ || (y < clipTop)
+ || (y >= clipBottom)
+ ) {
+ return;
+ }
+ X += offsetX;
+ Y += offsetY;
+ }
+
+ if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
+ dirty = true;
+ logical[X][Y].setForeColor(attr.getForeColor());
+ logical[X][Y].setBackColor(attr.getBackColor());
+ logical[X][Y].setBold(attr.getBold());
+ logical[X][Y].setBlink(attr.getBlink());
+ logical[X][Y].setReverse(attr.getReverse());
+ logical[X][Y].setUnderline(attr.getUnderline());
+ logical[X][Y].setProtect(attr.getProtect());
+ }
}
/**
* @param ch character to draw
* @param attr attributes to use (bold, foreColor, backColor)
*/
- public void putAll(char ch, CellAttributes attr) {
- for (int x = 0; x < width; x++) {
- for (int y = 0; y < height; y++) {
- putCharXY(x, y, ch, attr);
- }
- }
+ public final void putAll(final char ch, final CellAttributes attr) {
+
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y < height; y++) {
+ putCharXY(x, y, ch, attr);
+ }
+ }
}
/**
* @param y row coordinate. 0 is the top-most row.
* @param ch character + attributes to draw
*/
- public void putCharXY(int x, int y, Cell ch) {
- putCharXY(x, y, ch.ch, ch);
+ public final void putCharXY(final int x, final int y, final Cell ch) {
+ putCharXY(x, y, ch.getChar(), ch);
}
/**
* @param ch character to draw
* @param attr attributes to use (bold, foreColor, backColor)
*/
- public void putCharXY(int x, int y, char ch, CellAttributes attr) {
- if ((x < clipLeft) || (x >= clipRight) ||
- (y < clipTop) || (y >= clipBottom)) {
- return;
- }
-
- int X = x + offsetX;
- int Y = y + offsetY;
-
- // stderr.writefln("putCharXY: %d, %d, %c", X, Y, ch);
-
- if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
- dirty = true;
-
- // Do not put control characters on the display
- assert(ch >= 0x20);
- assert(ch != 0x7F);
-
- logical[X][Y].ch = ch;
- logical[X][Y].foreColor = attr.foreColor;
- logical[X][Y].backColor = attr.backColor;
- logical[X][Y].bold = attr.bold;
- logical[X][Y].blink = attr.blink;
- logical[X][Y].reverse = attr.reverse;
- logical[X][Y].underline = attr.underline;
- logical[X][Y].protect = attr.protect;
- }
+ public final void putCharXY(final int x, final int y, final char ch,
+ final CellAttributes attr) {
+
+ if ((x < clipLeft)
+ || (x >= clipRight)
+ || (y < clipTop)
+ || (y >= clipBottom)
+ ) {
+ return;
+ }
+
+ int X = x + offsetX;
+ int Y = y + offsetY;
+
+ // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch);
+
+ if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
+ dirty = true;
+
+ // Do not put control characters on the display
+ assert (ch >= 0x20);
+ assert (ch != 0x7F);
+
+ logical[X][Y].setChar(ch);
+ logical[X][Y].setForeColor(attr.getForeColor());
+ logical[X][Y].setBackColor(attr.getBackColor());
+ logical[X][Y].setBold(attr.getBold());
+ logical[X][Y].setBlink(attr.getBlink());
+ logical[X][Y].setReverse(attr.getReverse());
+ logical[X][Y].setUnderline(attr.getUnderline());
+ logical[X][Y].setProtect(attr.getProtect());
+ }
}
/**
* @param y row coordinate. 0 is the top-most row.
* @param ch character to draw
*/
- public void putCharXY(int x, int y, char ch) {
- if ((x < clipLeft) || (x >= clipRight) ||
- (y < clipTop) || (y >= clipBottom)) {
- return;
- }
+ public final void putCharXY(final int x, final int y, final char ch) {
+
+ if ((x < clipLeft)
+ || (x >= clipRight)
+ || (y < clipTop)
+ || (y >= clipBottom)
+ ) {
+ return;
+ }
- int X = x + offsetX;
- int Y = y + offsetY;
+ int X = x + offsetX;
+ int Y = y + offsetY;
- // stderr.writefln("putCharXY: %d, %d, %c", X, Y, ch);
+ // System.err.printf("putCharXY: %d, %d, %c\n", X, Y, ch);
- if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
- dirty = true;
- logical[X][Y].ch = ch;
- }
+ if ((X >= 0) && (X < width) && (Y >= 0) && (Y < height)) {
+ dirty = true;
+ logical[X][Y].setChar(ch);
+ }
}
/**
* @param str string to draw
* @param attr attributes to use (bold, foreColor, backColor)
*/
- public void putStrXY(int x, int y, String str, CellAttributes attr) {
- int i = x;
- for (int j = 0; j < str.length(); j++) {
- char ch = str.charAt(j);
- putCharXY(i, y, ch, attr);
- i++;
- if (i == width) {
- break;
- }
- }
+ public final void putStrXY(final int x, final int y, final String str,
+ final CellAttributes attr) {
+
+ int i = x;
+ for (int j = 0; j < str.length(); j++) {
+ char ch = str.charAt(j);
+ putCharXY(i, y, ch, attr);
+ i++;
+ if (i == width) {
+ break;
+ }
+ }
}
/**
* @param y row coordinate. 0 is the top-most row.
* @param str string to draw
*/
- public void putStrXY(int x, int y, String str) {
- int i = x;
- for (int j = 0; j < str.length(); j++) {
- char ch = str.charAt(j);
- putCharXY(i, y, ch);
- i++;
- if (i == width) {
- break;
- }
- }
+ public final void putStrXY(final int x, final int y, final String str) {
+
+ int i = x;
+ for (int j = 0; j < str.length(); j++) {
+ char ch = str.charAt(j);
+ putCharXY(i, y, ch);
+ i++;
+ if (i == width) {
+ break;
+ }
+ }
}
/**
- * Draw a vertical line from (x, y) to (x, y + n)
+ * Draw a vertical line from (x, y) to (x, y + n).
*
* @param x column coordinate. 0 is the left-most column.
* @param y row coordinate. 0 is the top-most row.
* @param ch character to draw
* @param attr attributes to use (bold, foreColor, backColor)
*/
- public void vLineXY(int x, int y, int n, char ch, CellAttributes attr) {
- for (int i = y; i < y + n; i++) {
- putCharXY(x, i, ch, attr);
- }
+ public final void vLineXY(final int x, final int y, final int n,
+ final char ch, final CellAttributes attr) {
+
+ for (int i = y; i < y + n; i++) {
+ putCharXY(x, i, ch, attr);
+ }
}
/**
- * Draw a horizontal line from (x, y) to (x + n, y)
+ * Draw a horizontal line from (x, y) to (x + n, y).
*
* @param x column coordinate. 0 is the left-most column.
* @param y row coordinate. 0 is the top-most row.
* @param ch character to draw
* @param attr attributes to use (bold, foreColor, backColor)
*/
- public void hLineXY(int x, int y, int n, char ch, CellAttributes attr) {
- for (int i = x; i < x + n; i++) {
- putCharXY(i, y, ch, attr);
- }
+ public final void hLineXY(final int x, final int y, final int n,
+ final char ch, final CellAttributes attr) {
+
+ for (int i = x; i < x + n; i++) {
+ putCharXY(i, y, ch, attr);
+ }
}
/**
* @param width new width
* @param height new height
*/
- private void reallocate(int width, int height) {
- if (logical != null) {
- for (int row = 0; row < this.height; row++) {
- for (int col = 0; col < this.width; col++) {
- logical[col][row] = null;
- }
- }
- logical = null;
- }
- logical = new Cell[width][height];
- if (physical != null) {
- for (int row = 0; row < this.height; row++) {
- for (int col = 0; col < this.width; col++) {
- physical[col][row] = null;
- }
- }
- physical = null;
- }
- physical = new Cell[width][height];
-
- for (int row = 0; row < height; row++) {
- for (int col = 0; col < width; col++) {
- physical[col][row] = new Cell();
- logical[col][row] = new Cell();
- }
- }
-
- this.width = width;
- this.height = height;
-
- clipLeft = 0;
- clipTop = 0;
- clipRight = width;
- clipBottom = height;
-
- reallyCleared = true;
- dirty = true;
+ private synchronized void reallocate(final int width, final int height) {
+ if (logical != null) {
+ for (int row = 0; row < this.height; row++) {
+ for (int col = 0; col < this.width; col++) {
+ logical[col][row] = null;
+ }
+ }
+ logical = null;
+ }
+ logical = new Cell[width][height];
+ if (physical != null) {
+ for (int row = 0; row < this.height; row++) {
+ for (int col = 0; col < this.width; col++) {
+ physical[col][row] = null;
+ }
+ }
+ physical = null;
+ }
+ physical = new Cell[width][height];
+
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ physical[col][row] = new Cell();
+ logical[col][row] = new Cell();
+ }
+ }
+
+ this.width = width;
+ this.height = height;
+
+ clipLeft = 0;
+ clipTop = 0;
+ clipRight = width;
+ clipBottom = height;
+
+ reallyCleared = true;
+ dirty = true;
}
/**
* Change the width. Everything on-screen will be destroyed and must be
* redrawn.
- *
+ *
* @param width new screen width
*/
- public void setWidth(int width) {
- reallocate(width, this.height);
+ public final synchronized void setWidth(final int width) {
+ reallocate(width, this.height);
}
/**
*
* @param height new screen height
*/
- public void setHeight(int height) {
- reallocate(this.width, height);
+ public final synchronized void setHeight(final int height) {
+ reallocate(this.width, height);
}
/**
* @param width new screen width
* @param height new screen height
*/
- public void setDimensions(int width, int height) {
- reallocate(width, height);
+ public final void setDimensions(final int width, final int height) {
+ reallocate(width, height);
}
/**
*
* @return current screen height
*/
- public int getHeight() {
- return this.height;
+ public final synchronized int getHeight() {
+ return this.height;
}
/**
*
* @return current screen width
*/
- public int getWidth() {
- return this.width;
+ public final synchronized int getWidth() {
+ return this.width;
}
/**
* Public constructor. Sets everything to not-bold, white-on-black.
*/
- public Screen() {
- debugToStderr = false;
-
- offsetX = 0;
- offsetY = 0;
- width = 80;
- height = 24;
- logical = null;
- physical = null;
- reallocate(width, height);
+ protected Screen() {
+ offsetX = 0;
+ offsetY = 0;
+ width = 80;
+ height = 24;
+ logical = null;
+ physical = null;
+ reallocate(width, height);
}
/**
* Reset screen to not-bold, white-on-black. Also flushes the offset and
* clip variables.
*/
- public void reset() {
- dirty = true;
- for (int row = 0; row < height; row++) {
- for (int col = 0; col < width; col++) {
- logical[col][row].reset();
- }
- }
- resetClipping();
+ public final synchronized void reset() {
+ dirty = true;
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ logical[col][row].reset();
+ }
+ }
+ resetClipping();
}
/**
* Flush the offset and clip variables.
*/
- public void resetClipping() {
- offsetX = 0;
- offsetY = 0;
- clipLeft = 0;
- clipTop = 0;
- clipRight = width;
- clipBottom = height;
+ public final void resetClipping() {
+ offsetX = 0;
+ offsetY = 0;
+ clipLeft = 0;
+ clipTop = 0;
+ clipRight = width;
+ clipBottom = height;
}
/**
- * Force the screen to be fully cleared and redrawn on the next flush().
+ * Clear the logical screen.
*/
- public void clear() {
- reset();
+ public final void clear() {
+ reset();
+ }
+
+ /**
+ * Clear the physical screen.
+ */
+ public final void clearPhysical() {
+ dirty = true;
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ physical[col][row].reset();
+ }
+ }
}
/**
* @param top top row of the box. 0 is the top-most row.
* @param right right column of box
* @param bottom bottom row of the box
- * @param border attributes to use for the border (bold, foreColor, backColor)
+ * @param border attributes to use for the border
* @param background attributes to use for the background
*/
- public void drawBox(int left, int top, int right, int bottom,
- CellAttributes border, CellAttributes background) {
- drawBox(left, top, right, bottom, border, background, 1, false);
+ public final void drawBox(final int left, final int top,
+ final int right, final int bottom,
+ final CellAttributes border, final CellAttributes background) {
+
+ drawBox(left, top, right, bottom, border, background, 1, false);
}
/**
* @param top top row of the box. 0 is the top-most row.
* @param right right column of box
* @param bottom bottom row of the box
- * @param border attributes to use for the border (bold, foreColor, backColor)
+ * @param border attributes to use for the border
* @param background attributes to use for the background
- * @param borderType = 1: single-line border
- * 2: double-line borders
- * 3: double-line top/bottom edges and single-line left/right edges
+ * @param borderType if 1, draw a single-line border; if 2, draw a
+ * double-line border; if 3, draw double-line top/bottom edges and
+ * single-line left/right edges (like Qmodem)
* @param shadow if true, draw a "shadow" on the box
*/
- public void drawBox(int left, int top, int right, int bottom,
- CellAttributes border, CellAttributes background, int borderType,
- boolean shadow) {
-
- int boxTop = top;
- int boxLeft = left;
- int boxWidth = right - left;
- int boxHeight = bottom - top;
-
- char cTopLeft;
- char cTopRight;
- char cBottomLeft;
- char cBottomRight;
- char cHSide;
- char cVSide;
-
- switch (borderType) {
- case 1:
- cTopLeft = GraphicsChars.ULCORNER;
- cTopRight = GraphicsChars.URCORNER;
- cBottomLeft = GraphicsChars.LLCORNER;
- cBottomRight = GraphicsChars.LRCORNER;
- cHSide = GraphicsChars.SINGLE_BAR;
- cVSide = GraphicsChars.WINDOW_SIDE;
- break;
-
- case 2:
- cTopLeft = GraphicsChars.WINDOW_LEFT_TOP_DOUBLE;
- cTopRight = GraphicsChars.WINDOW_RIGHT_TOP_DOUBLE;
- cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM_DOUBLE;
- cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM_DOUBLE;
- cHSide = GraphicsChars.DOUBLE_BAR;
- cVSide = GraphicsChars.WINDOW_SIDE_DOUBLE;
- break;
-
- case 3:
- cTopLeft = GraphicsChars.WINDOW_LEFT_TOP;
- cTopRight = GraphicsChars.WINDOW_RIGHT_TOP;
- cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM;
- cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM;
- cHSide = GraphicsChars.WINDOW_TOP;
- cVSide = GraphicsChars.WINDOW_SIDE;
- break;
- default:
- throw new IllegalArgumentException("Invalid border type: " + borderType);
- }
-
- // Place the corner characters
- putCharXY(left, top, cTopLeft, border);
- putCharXY(left + boxWidth - 1, top, cTopRight, border);
- putCharXY(left, top + boxHeight - 1, cBottomLeft, border);
- putCharXY(left + boxWidth - 1, top + boxHeight - 1, cBottomRight,
- border);
-
- // Draw the box lines
- hLineXY(left + 1, top, boxWidth - 2, cHSide, border);
- vLineXY(left, top + 1, boxHeight - 2, cVSide, border);
- hLineXY(left + 1, top + boxHeight - 1, boxWidth - 2, cHSide, border);
- vLineXY(left + boxWidth - 1, top + 1, boxHeight - 2, cVSide, border);
-
- // Fill in the interior background
- for (int i = 1; i < boxHeight - 1; i++) {
- hLineXY(1 + left, i + top, boxWidth - 2, ' ', background);
- }
-
- if (shadow) {
- // Draw a shadow
- drawBoxShadow(left, top, right, bottom);
- }
- }
-
- /**
- * Draw a box shadow
+ public final void drawBox(final int left, final int top,
+ final int right, final int bottom,
+ final CellAttributes border, final CellAttributes background,
+ final int borderType, final boolean shadow) {
+
+ int boxTop = top;
+ int boxLeft = left;
+ int boxWidth = right - left;
+ int boxHeight = bottom - top;
+
+ char cTopLeft;
+ char cTopRight;
+ char cBottomLeft;
+ char cBottomRight;
+ char cHSide;
+ char cVSide;
+
+ switch (borderType) {
+ case 1:
+ cTopLeft = GraphicsChars.ULCORNER;
+ cTopRight = GraphicsChars.URCORNER;
+ cBottomLeft = GraphicsChars.LLCORNER;
+ cBottomRight = GraphicsChars.LRCORNER;
+ cHSide = GraphicsChars.SINGLE_BAR;
+ cVSide = GraphicsChars.WINDOW_SIDE;
+ break;
+
+ case 2:
+ cTopLeft = GraphicsChars.WINDOW_LEFT_TOP_DOUBLE;
+ cTopRight = GraphicsChars.WINDOW_RIGHT_TOP_DOUBLE;
+ cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM_DOUBLE;
+ cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM_DOUBLE;
+ cHSide = GraphicsChars.DOUBLE_BAR;
+ cVSide = GraphicsChars.WINDOW_SIDE_DOUBLE;
+ break;
+
+ case 3:
+ cTopLeft = GraphicsChars.WINDOW_LEFT_TOP;
+ cTopRight = GraphicsChars.WINDOW_RIGHT_TOP;
+ cBottomLeft = GraphicsChars.WINDOW_LEFT_BOTTOM;
+ cBottomRight = GraphicsChars.WINDOW_RIGHT_BOTTOM;
+ cHSide = GraphicsChars.WINDOW_TOP;
+ cVSide = GraphicsChars.WINDOW_SIDE;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid border type: "
+ + borderType);
+ }
+
+ // Place the corner characters
+ putCharXY(left, top, cTopLeft, border);
+ putCharXY(left + boxWidth - 1, top, cTopRight, border);
+ putCharXY(left, top + boxHeight - 1, cBottomLeft, border);
+ putCharXY(left + boxWidth - 1, top + boxHeight - 1, cBottomRight,
+ border);
+
+ // Draw the box lines
+ hLineXY(left + 1, top, boxWidth - 2, cHSide, border);
+ vLineXY(left, top + 1, boxHeight - 2, cVSide, border);
+ hLineXY(left + 1, top + boxHeight - 1, boxWidth - 2, cHSide, border);
+ vLineXY(left + boxWidth - 1, top + 1, boxHeight - 2, cVSide, border);
+
+ // Fill in the interior background
+ for (int i = 1; i < boxHeight - 1; i++) {
+ hLineXY(1 + left, i + top, boxWidth - 2, ' ', background);
+ }
+
+ if (shadow) {
+ // Draw a shadow
+ drawBoxShadow(left, top, right, bottom);
+ }
+ }
+
+ /**
+ * Draw a box shadow.
*
* @param left left column of box. 0 is the left-most row.
* @param top top row of the box. 0 is the top-most row.
* @param right right column of box
* @param bottom bottom row of the box
*/
- public void drawBoxShadow(int left, int top, int right, int bottom) {
-
- int boxTop = top;
- int boxLeft = left;
- int boxWidth = right - left;
- int boxHeight = bottom - top;
- CellAttributes shadowAttr = new CellAttributes();
-
- // Shadows do not honor clipping but they DO honor offset.
- int oldClipRight = clipRight;
- int oldClipBottom = clipBottom;
- /*
- clipRight = boxWidth + 2;
- clipBottom = boxHeight + 1;
- */
- clipRight = width;
- clipBottom = height;
-
- for (int i = 0; i < boxHeight; i++) {
- putAttrXY(boxLeft + boxWidth, boxTop + 1 + i, shadowAttr);
- putAttrXY(boxLeft + boxWidth + 1, boxTop + 1 + i, shadowAttr);
- }
- for (int i = 0; i < boxWidth; i++) {
- putAttrXY(boxLeft + 2 + i, boxTop + boxHeight, shadowAttr);
- }
- clipRight = oldClipRight;
- clipBottom = oldClipBottom;
+ public final void drawBoxShadow(final int left, final int top,
+ final int right, final int bottom) {
+
+ int boxTop = top;
+ int boxLeft = left;
+ int boxWidth = right - left;
+ int boxHeight = bottom - top;
+ CellAttributes shadowAttr = new CellAttributes();
+
+ // Shadows do not honor clipping but they DO honor offset.
+ int oldClipRight = clipRight;
+ int oldClipBottom = clipBottom;
+ /*
+ clipRight = boxWidth + 2;
+ clipBottom = boxHeight + 1;
+ */
+ clipRight = width;
+ clipBottom = height;
+
+ for (int i = 0; i < boxHeight; i++) {
+ putAttrXY(boxLeft + boxWidth, boxTop + 1 + i, shadowAttr);
+ putAttrXY(boxLeft + boxWidth + 1, boxTop + 1 + i, shadowAttr);
+ }
+ for (int i = 0; i < boxWidth; i++) {
+ putAttrXY(boxLeft + 2 + i, boxTop + boxHeight, shadowAttr);
+ }
+ clipRight = oldClipRight;
+ clipBottom = oldClipBottom;
}
/**
* Subclasses must provide an implementation to push the logical screen
* to the physical device.
*/
- abstract public void flushPhysical();
+ public abstract void flushPhysical();
/**
* Put the cursor at (x,y).
* @param x column coordinate to put the cursor on
* @param y row coordinate to put the cursor on
*/
- public void putCursor(boolean visible, int x, int y) {
- cursorVisible = visible;
- cursorX = x;
- cursorY = y;
+ public void putCursor(final boolean visible, final int x, final int y) {
+
+ cursorVisible = visible;
+ cursorX = x;
+ cursorY = y;
}
/**
- * Hide the cursor
+ * Hide the cursor.
*/
- public void hideCursor() {
- cursorVisible = false;
+ public final void hideCursor() {
+ cursorVisible = false;
}
}