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]
31 import java
.util
.List
;
33 import jexer
.bits
.CellAttributes
;
34 import jexer
.bits
.GraphicsChars
;
35 import jexer
.event
.TKeypressEvent
;
36 import jexer
.event
.TMouseEvent
;
37 import static jexer
.TKeypress
.*;
40 * TComboBox implements a combobox containing a drop-down list and edit
41 * field. Alt-Down can be used to show the drop-down.
43 public class TComboBox
extends TWidget
{
45 // ------------------------------------------------------------------------
46 // Variables --------------------------------------------------------------
47 // ------------------------------------------------------------------------
50 * The list of items in the drop-down.
55 * The edit field containing the value to return.
60 * The action to perform when the user selects an item (clicks or enter).
62 private TAction updateAction
= null;
65 * If true, the field cannot be updated to a value not on the list.
67 private boolean limitToListValue
= true;
69 // ------------------------------------------------------------------------
70 // Constructors -----------------------------------------------------------
71 // ------------------------------------------------------------------------
76 * @param parent parent widget
77 * @param x column relative to parent
78 * @param y row relative to parent
79 * @param width visible combobox width, including the down-arrow
80 * @param values the possible values for the box, shown in the drop-down
81 * @param valuesIndex the initial index in values, or -1 for no default
83 * @param valuesHeight the height of the values drop-down when it is
85 * @param updateAction action to call when a new value is selected from
86 * the list or enter is pressed in the edit field
88 public TComboBox(final TWidget parent
, final int x
, final int y
,
89 final int width
, final List
<String
> values
, final int valuesIndex
,
90 final int valuesHeight
, final TAction updateAction
) {
92 // Set parent and window
93 super(parent
, x
, y
, width
, 1);
95 assert (values
!= null);
97 this.updateAction
= updateAction
;
99 field
= new TField(this, 0, 0, width
- 3, false, "",
101 if (valuesIndex
>= 0) {
102 field
.setText(values
.get(valuesIndex
));
105 list
= new TList(this, values
, 0, 1, width
, valuesHeight
,
108 field
.setText(list
.getSelected());
109 list
.setEnabled(false);
110 list
.setVisible(false);
111 TComboBox
.this.setHeight(1);
112 if (TComboBox
.this.limitToListValue
== false) {
113 TComboBox
.this.activate(field
);
115 if (updateAction
!= null) {
121 if (valuesIndex
>= 0) {
122 list
.setSelectedIndex(valuesIndex
);
125 list
.setEnabled(false);
126 list
.setVisible(false);
128 if (limitToListValue
) {
129 field
.setEnabled(false);
135 // ------------------------------------------------------------------------
136 // Event handlers ---------------------------------------------------------
137 // ------------------------------------------------------------------------
140 * Returns true if the mouse is currently on the down arrow.
142 * @param mouse mouse event
143 * @return true if the mouse is currently on the down arrow
145 private boolean mouseOnArrow(final TMouseEvent mouse
) {
146 if ((mouse
.getY() == 0)
147 && (mouse
.getX() >= getWidth() - 3)
148 && (mouse
.getX() <= getWidth() - 1)
156 * Handle mouse down clicks.
158 * @param mouse mouse button down event
161 public void onMouseDown(final TMouseEvent mouse
) {
162 if ((mouseOnArrow(mouse
)) && (mouse
.isMouse1())) {
163 // Make the list visible or not.
164 if (list
.isActive()) {
165 list
.setEnabled(false);
166 list
.setVisible(false);
168 if (limitToListValue
== false) {
172 list
.setEnabled(true);
173 list
.setVisible(true);
174 setHeight(list
.getHeight() + 1);
179 // Pass to parent for the things we don't care about.
180 super.onMouseDown(mouse
);
186 * @param keypress keystroke event
189 public void onKeypress(final TKeypressEvent keypress
) {
190 if (keypress
.equals(kbEsc
)) {
191 if (list
.isActive()) {
192 list
.setEnabled(false);
193 list
.setVisible(false);
195 if (limitToListValue
== false) {
202 if (keypress
.equals(kbAltDown
)) {
203 list
.setEnabled(true);
204 list
.setVisible(true);
205 setHeight(list
.getHeight() + 1);
210 if (keypress
.equals(kbTab
)
211 || (keypress
.equals(kbShiftTab
))
212 || (keypress
.equals(kbBackTab
))
214 if (list
.isActive()) {
215 list
.setEnabled(false);
216 list
.setVisible(false);
218 if (limitToListValue
== false) {
225 // Pass to parent for the things we don't care about.
226 super.onKeypress(keypress
);
229 // ------------------------------------------------------------------------
230 // TWidget ----------------------------------------------------------------
231 // ------------------------------------------------------------------------
234 * Draw the combobox down arrow.
238 CellAttributes comboBoxColor
;
240 if (!isAbsoluteActive()) {
241 // We lost focus, turn off the list.
242 if (list
.isActive()) {
243 list
.setEnabled(false);
244 list
.setVisible(false);
246 if (limitToListValue
== false) {
252 if (isAbsoluteActive()) {
253 comboBoxColor
= getTheme().getColor("tcombobox.active");
255 comboBoxColor
= getTheme().getColor("tcombobox.inactive");
258 putCharXY(getWidth() - 3, 0, GraphicsChars
.DOWNARROWLEFT
,
260 putCharXY(getWidth() - 2, 0, GraphicsChars
.DOWNARROW
,
262 putCharXY(getWidth() - 1, 0, GraphicsChars
.DOWNARROWRIGHT
,
266 // ------------------------------------------------------------------------
267 // TComboBox --------------------------------------------------------------
268 // ------------------------------------------------------------------------
271 * Get combobox text value.
273 * @return text in the edit field
275 public String
getText() {
276 return field
.getText();
280 * Set combobox text value.
282 * @param text the new text in the edit field
284 public void setText(final String text
) {
289 * Set combobox text value.
291 * @param text the new text in the edit field
292 * @param caseSensitive if true, perform a case-sensitive search for the
295 public void setText(final String text
, final boolean caseSensitive
) {
297 for (int i
= 0; i
< list
.getMaxSelectedIndex(); i
++) {
298 if (caseSensitive
== true) {
299 if (list
.getListItem(i
).equals(text
)) {
300 list
.setSelectedIndex(i
);
304 if (list
.getListItem(i
).toLowerCase().equals(text
.toLowerCase())) {
305 list
.setSelectedIndex(i
);
310 list
.setSelectedIndex(-1);
314 * Set combobox text to one of the list values.
316 * @param index the index in the list
318 public void setIndex(final int index
) {
319 list
.setSelectedIndex(index
);
320 field
.setText(list
.getSelected());
324 * Get a copy of the list of strings to display.
326 * @return the list of strings
328 public final List
<String
> getList() {
329 return list
.getList();
333 * Set the new list of strings to display.
335 * @param list new list of strings
337 public final void setList(final List
<String
> list
) {
338 this.list
.setList(list
);