2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2019 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]
29 package jexer
.teditor
;
31 import java
.util
.ArrayList
;
32 import java
.util
.List
;
34 import jexer
.bits
.CellAttributes
;
37 * A Line represents a single line of text on the screen, as a collection of
42 // ------------------------------------------------------------------------
43 // Variables --------------------------------------------------------------
44 // ------------------------------------------------------------------------
49 private ArrayList
<Word
> words
= new ArrayList
<Word
>();
52 * The default color for the TEditor class.
54 private CellAttributes defaultColor
= null;
57 * The text highlighter to use.
59 private Highlighter highlighter
= null;
62 * The current cursor position on this line.
64 private int cursor
= 0;
67 * The raw text of this line, what is passed to Word to determine
68 * highlighting behavior.
70 private StringBuilder rawText
;
72 // ------------------------------------------------------------------------
73 // Constructors -----------------------------------------------------------
74 // ------------------------------------------------------------------------
77 * Construct a new Line from an existing text string, and highlight
80 * @param str the text string
81 * @param defaultColor the color for unhighlighted text
82 * @param highlighter the highlighter to use
84 public Line(final String str
, final CellAttributes defaultColor
,
85 final Highlighter highlighter
) {
87 this.defaultColor
= defaultColor
;
88 this.highlighter
= highlighter
;
89 this.rawText
= new StringBuilder(str
);
95 * Construct a new Line from an existing text string.
97 * @param str the text string
98 * @param defaultColor the color for unhighlighted text
100 public Line(final String str
, final CellAttributes defaultColor
) {
101 this(str
, defaultColor
, null);
104 // ------------------------------------------------------------------------
105 // Line -------------------------------------------------------------------
106 // ------------------------------------------------------------------------
109 * Get a (shallow) copy of the words in this line.
111 * @return a copy of the word list
113 public List
<Word
> getWords() {
114 return new ArrayList
<Word
>(words
);
118 * Get the current cursor position.
120 * @return the cursor position
122 public int getCursor() {
127 * Set the current cursor position.
129 * @param cursor the new cursor position
131 public void setCursor(final int cursor
) {
133 || ((cursor
>= getDisplayLength())
134 && (getDisplayLength() > 0))
136 throw new IndexOutOfBoundsException("Max length is " +
137 getDisplayLength() + ", requested position " + cursor
);
139 this.cursor
= cursor
;
143 * Get the on-screen display length.
145 * @return the number of cells needed to display this line
147 public int getDisplayLength() {
148 int n
= rawText
.length();
150 // For now just return the raw text length.
152 // If we have any visible characters, add one to the display so
153 // that the cursor is immediately after the data.
160 * Get the raw string that matches this line.
164 public String
getRawString() {
165 return rawText
.toString();
169 * Scan rawText and make words out of it.
171 private void scanLine() {
173 Word word
= new Word(this.defaultColor
, this.highlighter
);
175 for (int i
= 0; i
< rawText
.length(); i
++) {
176 char ch
= rawText
.charAt(i
);
177 Word newWord
= word
.addChar(ch
);
178 if (newWord
!= word
) {
183 for (Word w
: words
) {
189 * Decrement the cursor by one. If at the first column, do nothing.
191 * @return true if the cursor position changed
193 public boolean left() {
202 * Increment the cursor by one. If at the last column, do nothing.
204 * @return true if the cursor position changed
206 public boolean right() {
207 if (getDisplayLength() == 0) {
210 if (cursor
== getDisplayLength() - 1) {
218 * Go to the first column of this line.
220 * @return true if the cursor position changed
222 public boolean home() {
231 * Go to the last column of this line.
233 * @return true if the cursor position changed
235 public boolean end() {
236 if (cursor
!= getDisplayLength() - 1) {
237 cursor
= getDisplayLength() - 1;
247 * Delete the character under the cursor.
250 assert (words
.size() > 0);
252 if (cursor
< getDisplayLength()) {
253 rawText
.deleteCharAt(cursor
);
256 // Re-scan the line to determine the new word boundaries.
261 * Delete the character immediately preceeding the cursor.
263 public void backspace() {
270 * Insert a character at the cursor.
272 * @param ch the character to insert
274 public void addChar(final char ch
) {
275 if (cursor
< getDisplayLength() - 1) {
276 rawText
.insert(cursor
, ch
);
285 * Replace a character at the cursor.
287 * @param ch the character to replace
289 public void replaceChar(final char ch
) {
290 if (cursor
< getDisplayLength() - 1) {
291 rawText
.setCharAt(cursor
, ch
);