2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2016 Kevin Lamonte
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
31 import static jexer
.TKeypress
.kbDown
;
32 import static jexer
.TKeypress
.kbEnd
;
33 import static jexer
.TKeypress
.kbHome
;
34 import static jexer
.TKeypress
.kbLeft
;
35 import static jexer
.TKeypress
.kbPgDn
;
36 import static jexer
.TKeypress
.kbPgUp
;
37 import static jexer
.TKeypress
.kbRight
;
38 import static jexer
.TKeypress
.kbUp
;
40 import java
.util
.LinkedList
;
41 import java
.util
.List
;
43 import jexer
.bits
.CellAttributes
;
44 import jexer
.event
.TKeypressEvent
;
45 import jexer
.event
.TMouseEvent
;
48 * TText implements a simple scrollable text area. It reflows automatically on
51 public final class TText
extends TWidget
{
59 * Text converted to lines.
61 private List
<String
> lines
;
66 private String colorKey
;
71 private TVScroller vScroller
;
74 * Horizontal scrollbar.
76 private THScroller hScroller
;
79 * Maximum width of a single line.
81 private int maxLineWidth
;
84 * Number of lines between each paragraph.
86 private int lineSpacing
= 1;
89 * Convenience method used by TWindowLoggerOutput.
94 public void addLine(final String line
) {
95 if (text
.length() == 0) {
105 * Recompute the bounds for the scrollbars.
107 private void computeBounds() {
109 for (String line
: lines
) {
110 if (line
.length() > maxLineWidth
) {
111 maxLineWidth
= line
.length();
115 vScroller
.setBottomValue((lines
.size() - getHeight()) + 1);
116 if (vScroller
.getBottomValue() < 0) {
117 vScroller
.setBottomValue(0);
119 if (vScroller
.getValue() > vScroller
.getBottomValue()) {
120 vScroller
.setValue(vScroller
.getBottomValue());
123 hScroller
.setRightValue((maxLineWidth
- getWidth()) + 1);
124 if (hScroller
.getRightValue() < 0) {
125 hScroller
.setRightValue(0);
127 if (hScroller
.getValue() > hScroller
.getRightValue()) {
128 hScroller
.setValue(hScroller
.getRightValue());
133 * Insert newlines into a string to wrap it to a maximum column. Terminate
134 * the final string with a newline. Note that interior newlines are
135 * converted to spaces.
140 * the maximum number of characters in a line
141 * @return the wrapped string
143 private String
wrap(final String str
, final int n
) {
146 StringBuilder sb
= new StringBuilder();
147 StringBuilder word
= new StringBuilder();
149 for (int i
= 0; i
< str
.length(); i
++) {
150 char ch
= str
.charAt(i
);
155 sb
.append(word
.toString());
157 if (word
.length() >= (n
- 1)) {
161 word
= new StringBuilder();
167 if (col
>= (n
- 1)) {
172 sb
.append(word
.toString());
174 return sb
.toString();
178 * Resize text and scrollbars for a new width/height.
180 public void reflow() {
184 // Break up text into paragraphs
185 String
[] paragraphs
= text
.split("\n\n");
186 for (String p
: paragraphs
) {
187 String paragraph
= wrap(p
, getWidth() - 1);
188 for (String line
: paragraph
.split("\n")) {
191 for (int i
= 0; i
< lineSpacing
; i
++) {
197 if (vScroller
== null) {
198 vScroller
= new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
199 vScroller
.setTopValue(0);
200 vScroller
.setValue(0);
202 vScroller
.setX(getWidth() - 1);
203 vScroller
.setHeight(getHeight() - 1);
205 vScroller
.setBigChange(getHeight() - 1);
208 if (hScroller
== null) {
209 hScroller
= new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
210 hScroller
.setLeftValue(0);
211 hScroller
.setValue(0);
213 hScroller
.setY(getHeight() - 1);
214 hScroller
.setWidth(getWidth() - 1);
216 hScroller
.setBigChange(getWidth() - 1);
222 * Public constructor.
229 * column relative to parent
231 * row relative to parent
235 * height of text area
237 public TText(final TWidget parent
, final String text
, final int x
,
238 final int y
, final int width
, final int height
) {
240 this(parent
, text
, x
, y
, width
, height
, "ttext");
244 * Public constructor.
251 * column relative to parent
253 * row relative to parent
257 * height of text area
259 * ColorTheme key color to use for foreground text. Default is
262 public TText(final TWidget parent
, final String text
, final int x
,
263 final int y
, final int width
, final int height
,
264 final String colorKey
) {
266 // Set parent and window
267 super(parent
, x
, y
, width
, height
);
270 this.colorKey
= colorKey
;
272 lines
= new LinkedList
<String
>();
283 CellAttributes color
= getTheme().getColor(colorKey
);
285 int begin
= vScroller
.getValue();
287 for (int i
= begin
; i
< lines
.size(); i
++) {
288 String line
= lines
.get(i
);
289 if (hScroller
.getValue() < line
.length()) {
290 line
= line
.substring(hScroller
.getValue());
294 String formatString
= "%-" + Integer
.toString(getWidth() - 1) + "s";
295 getScreen().putStringXY(0, topY
, String
.format(formatString
, line
),
299 if (topY
>= (getHeight() - 1)) {
304 // Pad the rest with blank lines
305 for (int i
= topY
; i
< (getHeight() - 1); i
++) {
306 getScreen().hLineXY(0, i
, getWidth() - 1, ' ', color
);
312 * Handle mouse press events.
315 * mouse button press event
318 public void onMouseDown(final TMouseEvent mouse
) {
319 if (mouse
.isMouseWheelUp()) {
320 vScroller
.decrement();
323 if (mouse
.isMouseWheelDown()) {
324 vScroller
.increment();
329 super.onMouseDown(mouse
);
339 public void onKeypress(final TKeypressEvent keypress
) {
340 if (keypress
.equals(kbLeft
)) {
341 hScroller
.decrement();
342 } else if (keypress
.equals(kbRight
)) {
343 hScroller
.increment();
344 } else if (keypress
.equals(kbUp
)) {
345 vScroller
.decrement();
346 } else if (keypress
.equals(kbDown
)) {
347 vScroller
.increment();
348 } else if (keypress
.equals(kbPgUp
)) {
349 vScroller
.bigDecrement();
350 } else if (keypress
.equals(kbPgDn
)) {
351 vScroller
.bigIncrement();
352 } else if (keypress
.equals(kbHome
)) {
354 } else if (keypress
.equals(kbEnd
)) {
355 vScroller
.toBottom();
357 // Pass other keys (tab etc.) on
358 super.onKeypress(keypress
);