2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2017 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 java
.util
.ArrayList
;
32 import java
.util
.List
;
34 import jexer
.bits
.CellAttributes
;
35 import jexer
.event
.TKeypressEvent
;
36 import jexer
.event
.TMouseEvent
;
37 import static jexer
.TKeypress
.*;
40 * TList shows a list of strings, and lets the user select one.
42 public class TList
extends TScrollableWidget
{
44 // ------------------------------------------------------------------------
45 // Variables --------------------------------------------------------------
46 // ------------------------------------------------------------------------
49 * The list of strings to display.
51 private List
<String
> strings
;
56 private int selectedString
= -1;
59 * Maximum width of a single line.
61 private int maxLineWidth
;
64 * The action to perform when the user selects an item (clicks or enter).
66 private TAction enterAction
= null;
69 * The action to perform when the user navigates with keyboard.
71 private TAction moveAction
= null;
73 // ------------------------------------------------------------------------
74 // Constructors -----------------------------------------------------------
75 // ------------------------------------------------------------------------
80 * @param parent parent widget
81 * @param strings list of strings to show
82 * @param x column relative to parent
83 * @param y row relative to parent
84 * @param width width of text area
85 * @param height height of text area
87 public TList(final TWidget parent
, final List
<String
> strings
, final int x
,
88 final int y
, final int width
, final int height
) {
90 this(parent
, strings
, x
, y
, width
, height
, null);
96 * @param parent parent widget
97 * @param strings list of strings to show. This is allowed to be null
98 * and set later with setList() or by subclasses.
99 * @param x column relative to parent
100 * @param y row relative to parent
101 * @param width width of text area
102 * @param height height of text area
103 * @param enterAction action to perform when an item is selected
105 public TList(final TWidget parent
, final List
<String
> strings
, final int x
,
106 final int y
, final int width
, final int height
,
107 final TAction enterAction
) {
109 super(parent
, x
, y
, width
, height
);
110 this.enterAction
= enterAction
;
111 this.strings
= new ArrayList
<String
>();
112 if (strings
!= null) {
113 this.strings
.addAll(strings
);
116 hScroller
= new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
117 vScroller
= new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
122 * Public constructor.
124 * @param parent parent widget
125 * @param strings list of strings to show. This is allowed to be null
126 * and set later with setList() or by subclasses.
127 * @param x column relative to parent
128 * @param y row relative to parent
129 * @param width width of text area
130 * @param height height of text area
131 * @param enterAction action to perform when an item is selected
132 * @param moveAction action to perform when the user navigates to a new
133 * item with arrow/page keys
135 public TList(final TWidget parent
, final List
<String
> strings
, final int x
,
136 final int y
, final int width
, final int height
,
137 final TAction enterAction
, final TAction moveAction
) {
139 super(parent
, x
, y
, width
, height
);
140 this.enterAction
= enterAction
;
141 this.moveAction
= moveAction
;
142 this.strings
= new ArrayList
<String
>();
143 if (strings
!= null) {
144 this.strings
.addAll(strings
);
147 hScroller
= new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
148 vScroller
= new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
152 // ------------------------------------------------------------------------
153 // Event handlers ---------------------------------------------------------
154 // ------------------------------------------------------------------------
157 * Handle mouse press events.
159 * @param mouse mouse button press event
162 public void onMouseDown(final TMouseEvent mouse
) {
163 if (mouse
.isMouseWheelUp()) {
167 if (mouse
.isMouseWheelDown()) {
172 if ((mouse
.getX() < getWidth() - 1)
173 && (mouse
.getY() < getHeight() - 1)) {
174 if (getVerticalValue() + mouse
.getY() < strings
.size()) {
175 selectedString
= getVerticalValue() + mouse
.getY();
181 super.onMouseDown(mouse
);
185 * Handle mouse double click.
187 * @param mouse mouse double click event
190 public void onMouseDoubleClick(final TMouseEvent mouse
) {
191 if ((mouse
.getX() < getWidth() - 1)
192 && (mouse
.getY() < getHeight() - 1)) {
193 if (getVerticalValue() + mouse
.getY() < strings
.size()) {
194 selectedString
= getVerticalValue() + mouse
.getY();
201 super.onMouseDoubleClick(mouse
);
207 * @param keypress keystroke event
210 public void onKeypress(final TKeypressEvent keypress
) {
211 if (keypress
.equals(kbLeft
)) {
212 horizontalDecrement();
213 } else if (keypress
.equals(kbRight
)) {
214 horizontalIncrement();
215 } else if (keypress
.equals(kbUp
)) {
216 if (strings
.size() > 0) {
217 if (selectedString
>= 0) {
218 if (selectedString
> 0) {
219 if (selectedString
- getVerticalValue() == 0) {
225 selectedString
= strings
.size() - 1;
228 if (selectedString
>= 0) {
231 } else if (keypress
.equals(kbDown
)) {
232 if (strings
.size() > 0) {
233 if (selectedString
>= 0) {
234 if (selectedString
< strings
.size() - 1) {
236 if (selectedString
- getVerticalValue() == getHeight() - 1) {
244 if (selectedString
>= 0) {
247 } else if (keypress
.equals(kbPgUp
)) {
248 bigVerticalDecrement();
249 if (selectedString
>= 0) {
250 selectedString
-= getHeight() - 1;
251 if (selectedString
< 0) {
255 if (selectedString
>= 0) {
258 } else if (keypress
.equals(kbPgDn
)) {
259 bigVerticalIncrement();
260 if (selectedString
>= 0) {
261 selectedString
+= getHeight() - 1;
262 if (selectedString
> strings
.size() - 1) {
263 selectedString
= strings
.size() - 1;
266 if (selectedString
>= 0) {
269 } else if (keypress
.equals(kbHome
)) {
271 if (strings
.size() > 0) {
274 if (selectedString
>= 0) {
277 } else if (keypress
.equals(kbEnd
)) {
279 if (strings
.size() > 0) {
280 selectedString
= strings
.size() - 1;
282 if (selectedString
>= 0) {
285 } else if (keypress
.equals(kbTab
)) {
286 getParent().switchWidget(true);
287 } else if (keypress
.equals(kbShiftTab
) || keypress
.equals(kbBackTab
)) {
288 getParent().switchWidget(false);
289 } else if (keypress
.equals(kbEnter
)) {
290 if (selectedString
>= 0) {
294 // Pass other keys (tab etc.) on
295 super.onKeypress(keypress
);
299 // ------------------------------------------------------------------------
300 // TScrollableWidget ------------------------------------------------------
301 // ------------------------------------------------------------------------
304 * Resize for a new width/height.
307 public void reflowData() {
313 for (int i
= 0; i
< strings
.size(); i
++) {
314 String line
= strings
.get(i
);
315 if (line
.length() > maxLineWidth
) {
316 maxLineWidth
= line
.length();
320 setBottomValue(strings
.size() - getHeight() + 1);
321 if (getBottomValue() < 0) {
325 setRightValue(maxLineWidth
- getWidth() + 1);
326 if (getRightValue() < 0) {
332 * Draw the files list.
336 CellAttributes color
= null;
337 int begin
= getVerticalValue();
339 for (int i
= begin
; i
< strings
.size(); i
++) {
340 String line
= strings
.get(i
);
341 if (getHorizontalValue() < line
.length()) {
342 line
= line
.substring(getHorizontalValue());
346 if (i
== selectedString
) {
347 if (isAbsoluteActive()) {
348 color
= getTheme().getColor("tlist.selected");
350 color
= getTheme().getColor("tlist.selected.inactive");
352 } else if (isAbsoluteActive()) {
353 color
= getTheme().getColor("tlist");
355 color
= getTheme().getColor("tlist.inactive");
357 String formatString
= "%-" + Integer
.toString(getWidth() - 1) + "s";
358 getScreen().putStringXY(0, topY
, String
.format(formatString
, line
),
361 if (topY
>= getHeight() - 1) {
366 if (isAbsoluteActive()) {
367 color
= getTheme().getColor("tlist");
369 color
= getTheme().getColor("tlist.inactive");
372 // Pad the rest with blank lines
373 for (int i
= topY
; i
< getHeight() - 1; i
++) {
374 getScreen().hLineXY(0, i
, getWidth() - 1, ' ', color
);
378 // ------------------------------------------------------------------------
379 // TList ------------------------------------------------------------------
380 // ------------------------------------------------------------------------
383 * Get the selection index.
385 * @return -1 if nothing is selected, otherwise the index into the list
387 public final int getSelectedIndex() {
388 return selectedString
;
392 * Set the selected string index.
394 * @param index -1 to unselect, otherwise the index into the list
396 public final void setSelectedIndex(final int index
) {
397 selectedString
= index
;
401 * Get the selected string.
403 * @return the selected string, or null of nothing is selected yet
405 public final String
getSelected() {
406 if ((selectedString
>= 0) && (selectedString
<= strings
.size() - 1)) {
407 return strings
.get(selectedString
);
413 * Get the maximum selection index value.
415 * @return -1 if the list is empty
417 public final int getMaxSelectedIndex() {
418 return strings
.size() - 1;
422 * Set the new list of strings to display.
424 * @param list new list of strings
426 public final void setList(final List
<String
> list
) {
428 strings
.addAll(list
);
433 * Perform user selection action.
435 public void dispatchEnter() {
436 assert (selectedString
>= 0);
437 assert (selectedString
< strings
.size());
438 if (enterAction
!= null) {
444 * Perform list movement action.
446 public void dispatchMove() {
447 assert (selectedString
>= 0);
448 assert (selectedString
< strings
.size());
449 if (moveAction
!= null) {