#34 call onResize() when window size is changed
[fanfix.git] / src / jexer / TText.java
index 1750be113f636fe0385e885fe525fe04f095d361..0edb290a8a74f7de3e94bd8890961233844a8495 100644 (file)
@@ -3,7 +3,7 @@
  *
  * The MIT License (MIT)
  *
- * Copyright (C) 2016 Kevin Lamonte
+ * Copyright (C) 2017 Kevin Lamonte
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
  */
 package jexer;
 
-import static jexer.TKeypress.kbDown;
-import static jexer.TKeypress.kbEnd;
-import static jexer.TKeypress.kbHome;
-import static jexer.TKeypress.kbLeft;
-import static jexer.TKeypress.kbPgDn;
-import static jexer.TKeypress.kbPgUp;
-import static jexer.TKeypress.kbRight;
-import static jexer.TKeypress.kbUp;
-
 import java.util.LinkedList;
 import java.util.List;
 
 import jexer.bits.CellAttributes;
 import jexer.event.TKeypressEvent;
 import jexer.event.TMouseEvent;
+import static jexer.TKeypress.*;
 
 /**
  * TText implements a simple scrollable text area. It reflows automatically on
  * resize.
  */
-public final class TText extends TWidget {
+public class TText extends TScrollableWidget {
+
+    /**
+     * Available text justifications.
+     */
+    public enum Justification {
+        /**
+         * Left-justified text.
+         */
+        LEFT,
+
+        /**
+         * Centered text.
+         */
+        CENTER,
+
+        /**
+         * Right-justified text.
+         */
+        RIGHT,
+
+        /**
+         * Fully-justified text.
+         */
+        FULL,
+    }
+
+    /**
+     * How to justify the text.
+     */
+    private Justification justification = Justification.LEFT;
 
     /**
      * Text to display.
@@ -66,30 +88,38 @@ public final class TText extends TWidget {
     private String colorKey;
 
     /**
-     * Vertical scrollbar.
+     * Maximum width of a single line.
      */
-    private TVScroller vScroller;
+    private int maxLineWidth;
 
     /**
-     * Horizontal scrollbar.
+     * Number of lines between each paragraph.
      */
-    private THScroller hScroller;
+    private int lineSpacing = 1;
 
     /**
-     * Maximum width of a single line.
+     * Set the text.
+     *
+     * @param text new text to display
      */
-    private int maxLineWidth;
+    public void setText(final String text) {
+        this.text = text;
+        reflowData();
+    }
 
     /**
-     * Number of lines between each paragraph.
+     * Get the text.
+     *
+     * @return the text
      */
-    private int lineSpacing = 1;
+    public String getText() {
+        return text;
+    }
 
     /**
      * Convenience method used by TWindowLoggerOutput.
      *
-     * @param line
-     *            new line to add
+     * @param line new line to add
      */
     public void addLine(final String line) {
         if (text.length() == 0) {
@@ -98,7 +128,7 @@ public final class TText extends TWidget {
             text += "\n\n";
             text += line;
         }
-        reflow();
+        reflowData();
     }
 
     /**
@@ -112,6 +142,7 @@ public final class TText extends TWidget {
             }
         }
 
+        vScroller.setTopValue(0);
         vScroller.setBottomValue((lines.size() - getHeight()) + 1);
         if (vScroller.getBottomValue() < 0) {
             vScroller.setBottomValue(0);
@@ -120,6 +151,7 @@ public final class TText extends TWidget {
             vScroller.setValue(vScroller.getBottomValue());
         }
 
+        hScroller.setLeftValue(0);
         hScroller.setRightValue((maxLineWidth - getWidth()) + 1);
         if (hScroller.getRightValue() < 0) {
             hScroller.setRightValue(0);
@@ -130,109 +162,93 @@ public final class TText extends TWidget {
     }
 
     /**
-     * Insert newlines into a string to wrap it to a maximum column. Terminate
-     * the final string with a newline. Note that interior newlines are
-     * converted to spaces.
+     * Set justification.
      *
-     * @param str
-     *            the string
-     * @param n
-     *            the maximum number of characters in a line
-     * @return the wrapped string
+     * @param justification LEFT, CENTER, RIGHT, or FULL
      */
-    private String wrap(final String str, final int n) {
-        assert (n > 0);
-
-        StringBuilder sb = new StringBuilder();
-        StringBuilder word = new StringBuilder();
-        int col = 0;
-        for (int i = 0; i < str.length(); i++) {
-            char ch = str.charAt(i);
-            if (ch == '\n') {
-                ch = ' ';
-            }
-            if (ch == ' ') {
-                sb.append(word.toString());
-                sb.append(ch);
-                if (word.length() >= (n - 1)) {
-                    sb.append('\n');
-                    col = 0;
-                }
-                word = new StringBuilder();
-            } else {
-                word.append(ch);
-            }
+    public void setJustification(final Justification justification) {
+        this.justification = justification;
+        reflowData();
+    }
 
-            col++;
-            if (col >= (n - 1)) {
-                sb.append('\n');
-                col = 0;
-            }
-        }
-        sb.append(word.toString());
-        sb.append('\n');
-        return sb.toString();
+    /**
+     * Left-justify the text.
+     */
+    public void leftJustify() {
+        justification = Justification.LEFT;
+        reflowData();
+    }
+
+    /**
+     * Center-justify the text.
+     */
+    public void centerJustify() {
+        justification = Justification.CENTER;
+        reflowData();
+    }
+
+    /**
+     * Right-justify the text.
+     */
+    public void rightJustify() {
+        justification = Justification.RIGHT;
+        reflowData();
+    }
+
+    /**
+     * Fully-justify the text.
+     */
+    public void fullJustify() {
+        justification = Justification.FULL;
+        reflowData();
     }
 
     /**
      * Resize text and scrollbars for a new width/height.
      */
-    public void reflow() {
+    @Override
+    public void reflowData() {
         // Reset the lines
         lines.clear();
 
         // Break up text into paragraphs
         String[] paragraphs = text.split("\n\n");
         for (String p : paragraphs) {
-            String paragraph = wrap(p, getWidth() - 1);
-            for (String line : paragraph.split("\n")) {
-                lines.add(line);
+            switch (justification) {
+            case LEFT:
+                lines.addAll(jexer.bits.StringUtils.left(p,
+                        getWidth() - 1));
+                break;
+            case CENTER:
+                lines.addAll(jexer.bits.StringUtils.center(p,
+                        getWidth() - 1));
+                break;
+            case RIGHT:
+                lines.addAll(jexer.bits.StringUtils.right(p,
+                        getWidth() - 1));
+                break;
+            case FULL:
+                lines.addAll(jexer.bits.StringUtils.full(p,
+                        getWidth() - 1));
+                break;
             }
+
             for (int i = 0; i < lineSpacing; i++) {
                 lines.add("");
             }
         }
-
-        // Start at the top
-        if (vScroller == null) {
-            vScroller = new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
-            vScroller.setTopValue(0);
-            vScroller.setValue(0);
-        } else {
-            vScroller.setX(getWidth() - 1);
-            vScroller.setHeight(getHeight() - 1);
-        }
-        vScroller.setBigChange(getHeight() - 1);
-
-        // Start at the left
-        if (hScroller == null) {
-            hScroller = new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
-            hScroller.setLeftValue(0);
-            hScroller.setValue(0);
-        } else {
-            hScroller.setY(getHeight() - 1);
-            hScroller.setWidth(getWidth() - 1);
-        }
-        hScroller.setBigChange(getWidth() - 1);
-
         computeBounds();
     }
 
     /**
      * Public constructor.
      *
-     * @param parent
-     *            parent widget
-     * @param text
-     *            text on the screen
-     * @param x
-     *            column relative to parent
-     * @param y
-     *            row relative to parent
-     * @param width
-     *            width of text area
-     * @param height
-     *            height of text area
+     * @param parent parent widget
+     * @param text text on the screen
+     * @param x column relative to parent
+     * @param y row relative to parent
+     * @param width width of text area
+     * @param height height of text area
      */
     public TText(final TWidget parent, final String text, final int x,
             final int y, final int width, final int height) {
@@ -243,21 +259,14 @@ public final class TText extends TWidget {
     /**
      * Public constructor.
      *
-     * @param parent
-     *            parent widget
-     * @param text
-     *            text on the screen
-     * @param x
-     *            column relative to parent
-     * @param y
-     *            row relative to parent
-     * @param width
-     *            width of text area
-     * @param height
-     *            height of text area
-     * @param colorKey
-     *            ColorTheme key color to use for foreground text. Default is
-     *            "ttext"
+     * @param parent parent widget
+     * @param text text on the screen
+     * @param x column relative to parent
+     * @param y row relative to parent
+     * @param width width of text area
+     * @param height height of text area
+     * @param colorKey ColorTheme key color to use for foreground
+     * text. Default is "ttext".
      */
     public TText(final TWidget parent, final String text, final int x,
             final int y, final int width, final int height,
@@ -271,7 +280,9 @@ public final class TText extends TWidget {
 
         lines = new LinkedList<String>();
 
-        reflow();
+        vScroller = new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
+        hScroller = new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
+        reflowData();
     }
 
     /**
@@ -311,8 +322,7 @@ public final class TText extends TWidget {
     /**
      * Handle mouse press events.
      *
-     * @param mouse
-     *            mouse button press event
+     * @param mouse mouse button press event
      */
     @Override
     public void onMouseDown(final TMouseEvent mouse) {
@@ -332,8 +342,7 @@ public final class TText extends TWidget {
     /**
      * Handle keystrokes.
      *
-     * @param keypress
-     *            keystroke event
+     * @param keypress keystroke event
      */
     @Override
     public void onKeypress(final TKeypressEvent keypress) {