2 * Jexer - Java Text User Interface
4 * License: LGPLv3 or later
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
10 * Copyright (C) 2015 Kevin Lamonte
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
33 import static jexer
.TKeypress
.kbDown
;
34 import static jexer
.TKeypress
.kbEnd
;
35 import static jexer
.TKeypress
.kbHome
;
36 import static jexer
.TKeypress
.kbLeft
;
37 import static jexer
.TKeypress
.kbPgDn
;
38 import static jexer
.TKeypress
.kbPgUp
;
39 import static jexer
.TKeypress
.kbRight
;
40 import static jexer
.TKeypress
.kbUp
;
42 import java
.util
.LinkedList
;
43 import java
.util
.List
;
45 import jexer
.bits
.CellAttributes
;
46 import jexer
.event
.TKeypressEvent
;
47 import jexer
.event
.TMouseEvent
;
50 * TText implements a simple scrollable text area. It reflows automatically on
53 public final class TText
extends TWidget
{
61 * Text converted to lines.
63 private List
<String
> lines
;
68 private String colorKey
;
73 private TVScroller vScroller
;
76 * Horizontal scrollbar.
78 private THScroller hScroller
;
81 * Maximum width of a single line.
83 private int maxLineWidth
;
86 * Number of lines between each paragraph.
88 private int lineSpacing
= 1;
91 * Convenience method used by TWindowLoggerOutput.
96 public void addLine(final String line
) {
97 if (text
.length() == 0) {
107 * Recompute the bounds for the scrollbars.
109 private void computeBounds() {
111 for (String line
: lines
) {
112 if (line
.length() > maxLineWidth
) {
113 maxLineWidth
= line
.length();
117 vScroller
.setBottomValue((lines
.size() - getHeight()) + 1);
118 if (vScroller
.getBottomValue() < 0) {
119 vScroller
.setBottomValue(0);
121 if (vScroller
.getValue() > vScroller
.getBottomValue()) {
122 vScroller
.setValue(vScroller
.getBottomValue());
125 hScroller
.setRightValue((maxLineWidth
- getWidth()) + 1);
126 if (hScroller
.getRightValue() < 0) {
127 hScroller
.setRightValue(0);
129 if (hScroller
.getValue() > hScroller
.getRightValue()) {
130 hScroller
.setValue(hScroller
.getRightValue());
135 * Insert newlines into a string to wrap it to a maximum column. Terminate
136 * the final string with a newline. Note that interior newlines are
137 * converted to spaces.
142 * the maximum number of characters in a line
143 * @return the wrapped string
145 private String
wrap(final String str
, final int n
) {
148 StringBuilder sb
= new StringBuilder();
149 StringBuilder word
= new StringBuilder();
151 for (int i
= 0; i
< str
.length(); i
++) {
152 char ch
= str
.charAt(i
);
157 sb
.append(word
.toString());
159 if (word
.length() >= (n
- 1)) {
163 word
= new StringBuilder();
169 if (col
>= (n
- 1)) {
174 sb
.append(word
.toString());
176 return sb
.toString();
180 * Resize text and scrollbars for a new width/height.
182 public void reflow() {
186 // Break up text into paragraphs
187 String
[] paragraphs
= text
.split("\n\n");
188 for (String p
: paragraphs
) {
189 String paragraph
= wrap(p
, getWidth() - 1);
190 for (String line
: paragraph
.split("\n")) {
193 for (int i
= 0; i
< lineSpacing
; i
++) {
199 if (vScroller
== null) {
200 vScroller
= new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
201 vScroller
.setTopValue(0);
202 vScroller
.setValue(0);
204 vScroller
.setX(getWidth() - 1);
205 vScroller
.setHeight(getHeight() - 1);
207 vScroller
.setBigChange(getHeight() - 1);
210 if (hScroller
== null) {
211 hScroller
= new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
212 hScroller
.setLeftValue(0);
213 hScroller
.setValue(0);
215 hScroller
.setY(getHeight() - 1);
216 hScroller
.setWidth(getWidth() - 1);
218 hScroller
.setBigChange(getWidth() - 1);
224 * Public constructor.
231 * column relative to parent
233 * row relative to parent
237 * height of text area
239 public TText(final TWidget parent
, final String text
, final int x
,
240 final int y
, final int width
, final int height
) {
242 this(parent
, text
, x
, y
, width
, height
, "ttext");
246 * Public constructor.
253 * column relative to parent
255 * row relative to parent
259 * height of text area
261 * ColorTheme key color to use for foreground text. Default is
264 public TText(final TWidget parent
, final String text
, final int x
,
265 final int y
, final int width
, final int height
,
266 final String colorKey
) {
268 // Set parent and window
269 super(parent
, x
, y
, width
, height
);
272 this.colorKey
= colorKey
;
274 lines
= new LinkedList
<String
>();
285 CellAttributes color
= getTheme().getColor(colorKey
);
287 int begin
= vScroller
.getValue();
289 for (int i
= begin
; i
< lines
.size(); i
++) {
290 String line
= lines
.get(i
);
291 if (hScroller
.getValue() < line
.length()) {
292 line
= line
.substring(hScroller
.getValue());
296 String formatString
= "%-" + Integer
.toString(getWidth() - 1) + "s";
297 getScreen().putStrXY(0, topY
, String
.format(formatString
, line
),
301 if (topY
>= (getHeight() - 1)) {
306 // Pad the rest with blank lines
307 for (int i
= topY
; i
< (getHeight() - 1); i
++) {
308 getScreen().hLineXY(0, i
, getWidth() - 1, ' ', color
);
314 * Handle mouse press events.
317 * mouse button press event
320 public void onMouseDown(final TMouseEvent mouse
) {
321 if (mouse
.isMouseWheelUp()) {
322 vScroller
.decrement();
325 if (mouse
.isMouseWheelDown()) {
326 vScroller
.increment();
331 super.onMouseDown(mouse
);
341 public void onKeypress(final TKeypressEvent keypress
) {
342 if (keypress
.equals(kbLeft
)) {
343 hScroller
.decrement();
344 } else if (keypress
.equals(kbRight
)) {
345 hScroller
.increment();
346 } else if (keypress
.equals(kbUp
)) {
347 vScroller
.decrement();
348 } else if (keypress
.equals(kbDown
)) {
349 vScroller
.increment();
350 } else if (keypress
.equals(kbPgUp
)) {
351 vScroller
.bigDecrement();
352 } else if (keypress
.equals(kbPgDn
)) {
353 vScroller
.bigIncrement();
354 } else if (keypress
.equals(kbHome
)) {
356 } else if (keypress
.equals(kbEnd
)) {
357 vScroller
.toBottom();
359 // Pass other keys (tab etc.) on
360 super.onKeypress(keypress
);