LICENSE CHANGED TO MIT
[nikiroo-utils.git] / src / jexer / io / Screen.java
index 630725411a55210139995eb29b72a0a68f99a66a..720f8a9789f5222182bab77ec5b50fd3f74f318d 100644 (file)
@@ -1,29 +1,27 @@
-/**
+/*
  * Jexer - Java Text User Interface
  *
- * License: LGPLv3 or later
- *
- * 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.
+ * The MIT License (MIT)
  *
- *     Copyright (C) 2015  Kevin Lamonte
+ * Copyright (C) 2016 Kevin Lamonte
  *
- * This program 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 3 of
- * the License, or (at your option) any later version.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
  *
- * This program 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
- * General Public License for more details.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
  *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, see
- * http://www.gnu.org/licenses/, or write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
  * @author Kevin Lamonte [kevin.lamonte@gmail.com]
  * @version 1
@@ -53,32 +51,122 @@ public abstract class Screen {
     /**
      * Drawing offset for x.
      */
-    public int offsetX;
+    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.
      */
-    public int offsetY;
+    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.
      */
-    public int 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;
+    }
 
     /**
      * Ignore anything drawn below clipBottom.
      */
-    public int clipBottom;
+    private int clipBottom;
+
+    /**
+     * Get bottom drawing clipping boundary.
+     *
+     * @return drawing boundary
+     */
+    public final int getClipBottom() {
+        return clipBottom;
+    }
+
+    /**
+     * Set bottom drawing clipping boundary.
+     *
+     * @param clipBottom new boundary
+     */
+    public final void setClipBottom(final int clipBottom) {
+        this.clipBottom = clipBottom;
+    }
 
     /**
      * Ignore anything drawn left of clipLeft.
      */
-    public int clipLeft;
+    private int clipLeft;
+
+    /**
+     * Get left drawing clipping boundary.
+     *
+     * @return drawing boundary
+     */
+    public final int getClipLeft() {
+        return clipLeft;
+    }
+
+    /**
+     * Set left drawing clipping boundary.
+     *
+     * @param clipLeft new boundary
+     */
+    public final void setClipLeft(final int clipLeft) {
+        this.clipLeft = clipLeft;
+    }
 
     /**
      * Ignore anything drawn above clipTop.
      */
-    public int 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().
@@ -93,7 +181,17 @@ public abstract class Screen {
     /**
      * When true, logical != physical.
      */
-    public boolean dirty;
+    protected volatile boolean dirty;
+
+    /**
+     * Get dirty flag.
+     *
+     * @return if true, the logical screen is not in sync with the physical
+     * screen
+     */
+    public final boolean isDirty() {
+        return dirty;
+    }
 
     /**
      * Set if the user explicitly wants to redraw everything starting with a
@@ -124,9 +222,11 @@ public abstract class Screen {
      * @param y row coordinate.  0 is the top-most row.
      * @return attributes at (x, y)
      */
-    public CellAttributes getAttrXY(final int x, final int y) {
+    public final CellAttributes getAttrXY(final int x, final int y) {
         CellAttributes attr = new CellAttributes();
-        attr.setTo(logical[x][y]);
+        if ((x >= 0) && (x < width) && (y >= 0) && (y < height)) {
+            attr.setTo(logical[x][y]);
+        }
         return attr;
     }
 
@@ -137,7 +237,9 @@ public abstract class Screen {
      * @param y row coordinate.  0 is the top-most row.
      * @param attr attributes to use (bold, foreColor, backColor)
      */
-    public void putAttrXY(final int x, final int y, final CellAttributes attr) {
+    public final void putAttrXY(final int x, final int y,
+        final CellAttributes attr) {
+
         putAttrXY(x, y, attr, true);
     }
 
@@ -149,8 +251,8 @@ public abstract class Screen {
      * @param attr attributes to use (bold, foreColor, backColor)
      * @param clip if true, honor clipping/offset
      */
-    public void putAttrXY(final int x, final int y, final CellAttributes attr,
-        final boolean clip) {
+    public final void putAttrXY(final int x, final int y
+        , final CellAttributes attr, final boolean clip) {
 
         int X = x;
         int Y = y;
@@ -171,11 +273,11 @@ public abstract class Screen {
             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());
+            logical[X][Y].setBold(attr.isBold());
+            logical[X][Y].setBlink(attr.isBlink());
+            logical[X][Y].setReverse(attr.isReverse());
+            logical[X][Y].setUnderline(attr.isUnderline());
+            logical[X][Y].setProtect(attr.isProtect());
         }
     }
 
@@ -185,7 +287,8 @@ public abstract class Screen {
      * @param ch character to draw
      * @param attr attributes to use (bold, foreColor, backColor)
      */
-    public void putAll(final char ch, final CellAttributes 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);
@@ -200,7 +303,7 @@ public abstract class Screen {
      * @param y row coordinate.  0 is the top-most row.
      * @param ch character + attributes to draw
      */
-    public void putCharXY(final int x, final int y, final Cell ch) {
+    public final void putCharXY(final int x, final int y, final Cell ch) {
         putCharXY(x, y, ch.getChar(), ch);
     }
 
@@ -212,7 +315,7 @@ public abstract class Screen {
      * @param ch character to draw
      * @param attr attributes to use (bold, foreColor, backColor)
      */
-    public void putCharXY(final int x, final int y, final char ch,
+    public final void putCharXY(final int x, final int y, final char ch,
         final CellAttributes attr) {
 
         if ((x < clipLeft)
@@ -238,11 +341,11 @@ public abstract class Screen {
             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());
+            logical[X][Y].setBold(attr.isBold());
+            logical[X][Y].setBlink(attr.isBlink());
+            logical[X][Y].setReverse(attr.isReverse());
+            logical[X][Y].setUnderline(attr.isUnderline());
+            logical[X][Y].setProtect(attr.isProtect());
         }
     }
 
@@ -253,7 +356,8 @@ public abstract class Screen {
      * @param y row coordinate.  0 is the top-most row.
      * @param ch character to draw
      */
-    public void putCharXY(final int x, final int y, final char ch) {
+    public final void putCharXY(final int x, final int y, final char ch) {
+
         if ((x < clipLeft)
             || (x >= clipRight)
             || (y < clipTop)
@@ -281,7 +385,7 @@ public abstract class Screen {
      * @param str string to draw
      * @param attr attributes to use (bold, foreColor, backColor)
      */
-    public void putStrXY(final int x, final int y, final String str,
+    public final void putStringXY(final int x, final int y, final String str,
         final CellAttributes attr) {
 
         int i = x;
@@ -303,7 +407,8 @@ public abstract class Screen {
      * @param y row coordinate.  0 is the top-most row.
      * @param str string to draw
      */
-    public void putStrXY(final int x, final int y, final String str) {
+    public final void putStringXY(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);
@@ -324,8 +429,8 @@ public abstract class Screen {
      * @param ch character to draw
      * @param attr attributes to use (bold, foreColor, backColor)
      */
-    public void vLineXY(final int x, final int y, final int n, final char ch,
-        final CellAttributes 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);
@@ -341,8 +446,8 @@ public abstract class Screen {
      * @param ch character to draw
      * @param attr attributes to use (bold, foreColor, backColor)
      */
-    public void hLineXY(final int x, final int y, final int n, final char ch,
-        final CellAttributes 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);
@@ -355,7 +460,7 @@ public abstract class Screen {
      * @param width new width
      * @param height new height
      */
-    private void reallocate(final int width, final int height) {
+    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++) {
@@ -400,7 +505,7 @@ public abstract class Screen {
      *
      * @param width new screen width
      */
-    public void setWidth(final int width) {
+    public final synchronized void setWidth(final int width) {
         reallocate(width, this.height);
     }
 
@@ -410,7 +515,7 @@ public abstract class Screen {
      *
      * @param height new screen height
      */
-    public void setHeight(final int height) {
+    public final synchronized void setHeight(final int height) {
         reallocate(this.width, height);
     }
 
@@ -421,7 +526,7 @@ public abstract class Screen {
      * @param width new screen width
      * @param height new screen height
      */
-    public void setDimensions(final int width, final int height) {
+    public final void setDimensions(final int width, final int height) {
         reallocate(width, height);
     }
 
@@ -430,7 +535,7 @@ public abstract class Screen {
      *
      * @return current screen height
      */
-    public int getHeight() {
+    public final synchronized int getHeight() {
         return this.height;
     }
 
@@ -439,14 +544,14 @@ public abstract class Screen {
      *
      * @return current screen width
      */
-    public int getWidth() {
+    public final synchronized int getWidth() {
         return this.width;
     }
 
     /**
      * Public constructor.  Sets everything to not-bold, white-on-black.
      */
-    public Screen() {
+    protected Screen() {
         offsetX  = 0;
         offsetY  = 0;
         width    = 80;
@@ -460,7 +565,7 @@ public abstract class Screen {
      * Reset screen to not-bold, white-on-black.  Also flushes the offset and
      * clip variables.
      */
-    public void reset() {
+    public final synchronized void reset() {
         dirty = true;
         for (int row = 0; row < height; row++) {
             for (int col = 0; col < width; col++) {
@@ -473,7 +578,7 @@ public abstract class Screen {
     /**
      * Flush the offset and clip variables.
      */
-    public void resetClipping() {
+    public final void resetClipping() {
         offsetX    = 0;
         offsetY    = 0;
         clipLeft   = 0;
@@ -483,12 +588,24 @@ public abstract class Screen {
     }
 
     /**
-     * Force the screen to be fully cleared and redrawn on the next flush().
+     * Clear the logical screen.
      */
-    public void clear() {
+    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();
+            }
+        }
+    }
+
     /**
      * Draw a box with a border and empty background.
      *
@@ -499,7 +616,7 @@ public abstract class Screen {
      * @param border attributes to use for the border
      * @param background attributes to use for the background
      */
-    public void drawBox(final int left, final int top,
+    public final void drawBox(final int left, final int top,
         final int right, final int bottom,
         final CellAttributes border, final CellAttributes background) {
 
@@ -520,13 +637,11 @@ public abstract class Screen {
      * single-line left/right edges (like Qmodem)
      * @param shadow if true, draw a "shadow" on the box
      */
-    public void drawBox(final int left, final int top,
+    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;
 
@@ -594,14 +709,14 @@ public abstract class Screen {
     }
 
     /**
-     * Draw a box shadow
+     * 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(final int left, final int top,
+    public final void drawBoxShadow(final int left, final int top,
         final int right, final int bottom) {
 
         int boxTop = top;
@@ -635,7 +750,7 @@ public abstract class Screen {
      * 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).
@@ -645,15 +760,16 @@ public abstract class Screen {
      * @param y row coordinate to put the cursor on
      */
     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() {
+    public final void hideCursor() {
         cursorVisible = false;
     }
 }