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]
32 import jexer
.TKeypress
;
34 import jexer
.event
.TKeypressEvent
;
35 import static jexer
.TKeypress
.*;
38 * TTreeView implements a simple tree view.
40 public class TTreeView
extends TWidget
{
42 // ------------------------------------------------------------------------
43 // Variables --------------------------------------------------------------
44 // ------------------------------------------------------------------------
49 private TTreeItem treeRoot
;
52 * Only one of my children can be selected.
54 private TTreeItem selectedItem
= null;
57 * The action to perform when the user selects an item.
59 private TAction action
= null;
62 * The top line currently visible.
64 private int topLine
= 0;
67 * The left column currently visible.
69 private int leftColumn
= 0;
71 // ------------------------------------------------------------------------
72 // Constructors -----------------------------------------------------------
73 // ------------------------------------------------------------------------
78 * @param parent parent widget
79 * @param x column relative to parent
80 * @param y row relative to parent
81 * @param width width of tree view
82 * @param height height of tree view
84 public TTreeView(final TWidget parent
, final int x
, final int y
,
85 final int width
, final int height
) {
87 this(parent
, x
, y
, width
, height
, null);
93 * @param parent parent widget
94 * @param x column relative to parent
95 * @param y row relative to parent
96 * @param width width of tree view
97 * @param height height of tree view
98 * @param action action to perform when an item is selected
100 public TTreeView(final TWidget parent
, final int x
, final int y
,
101 final int width
, final int height
, final TAction action
) {
103 super(parent
, x
, y
, width
, height
);
104 this.action
= action
;
107 // ------------------------------------------------------------------------
108 // Event handlers ---------------------------------------------------------
109 // ------------------------------------------------------------------------
114 * @param keypress keystroke event
117 public void onKeypress(final TKeypressEvent keypress
) {
118 if (keypress
.equals(kbUp
)) {
119 // Select the previous item
120 if (selectedItem
!= null) {
121 if (selectedItem
.keyboardPrevious
!= null) {
122 setSelected(selectedItem
.keyboardPrevious
, true);
125 } else if (keypress
.equals(kbDown
)) {
126 // Select the next item
127 if (selectedItem
!= null) {
128 if (selectedItem
.keyboardNext
!= null) {
129 setSelected(selectedItem
.keyboardNext
, true);
132 } else if (keypress
.equals(kbPgDn
)) {
133 for (int i
= 0; i
< getHeight() - 1; i
++) {
134 onKeypress(new TKeypressEvent(TKeypress
.kbDown
));
136 } else if (keypress
.equals(kbPgUp
)) {
137 for (int i
= 0; i
< getHeight() - 1; i
++) {
138 onKeypress(new TKeypressEvent(TKeypress
.kbUp
));
140 } else if (keypress
.equals(kbHome
)) {
141 setSelected((TTreeItem
) getChildren().get(0), false);
143 } else if (keypress
.equals(kbEnd
)) {
144 setSelected((TTreeItem
) getChildren().get(getChildren().size() - 1),
147 if (selectedItem
!= null) {
148 selectedItem
.onKeypress(keypress
);
150 // Pass other keys (tab etc.) on to TWidget's handler.
151 super.onKeypress(keypress
);
156 // ------------------------------------------------------------------------
157 // TWidget ----------------------------------------------------------------
158 // ------------------------------------------------------------------------
161 // ------------------------------------------------------------------------
162 // TTreeView --------------------------------------------------------------
163 // ------------------------------------------------------------------------
166 * Get the root of the tree.
168 * @return the root of the tree
170 public final TTreeItem
getTreeRoot() {
175 * Set the root of the tree.
177 * @param treeRoot the new root of the tree
179 public final void setTreeRoot(final TTreeItem treeRoot
) {
180 this.treeRoot
= treeRoot
;
185 * Get the tree view item that was selected.
187 * @return the selected item, or null if no item is selected
189 public final TTreeItem
getSelected() {
194 * Set the new selected tree view item.
196 * @param item new item that became selected
197 * @param centerWindow if true, move the window to put the selected into
200 public void setSelected(final TTreeItem item
, final boolean centerWindow
) {
202 item
.setSelected(true);
204 if ((selectedItem
!= null) && (selectedItem
!= item
)) {
205 selectedItem
.setSelected(false);
211 for (TWidget widget
: getChildren()) {
212 if (widget
== selectedItem
) {
217 topLine
= y
- (getHeight() - 1)/2;
218 if (topLine
> getChildren().size() - getHeight()) {
219 topLine
= getChildren().size() - getHeight();
226 if (selectedItem
!= null) {
227 activate(selectedItem
);
232 * Perform user selection action.
234 public void dispatch() {
235 if (action
!= null) {
241 * Get the left column value. 0 is the leftmost column.
243 * @return the left column
245 public int getLeftColumn() {
250 * Set the left column value. 0 is the leftmost column.
252 * @param leftColumn the new left column
254 public void setLeftColumn(final int leftColumn
) {
255 this.leftColumn
= leftColumn
;
259 * Get the top line (row) value. 0 is the topmost line.
261 * @return the top line
263 public int getTopLine() {
268 * Set the top line value. 0 is the topmost line.
270 * @param topLine the new top line
272 public void setTopLine(final int topLine
) {
273 this.topLine
= topLine
;
277 * Get the total line (rows) count, based on the items that are visible
280 * @return the line count
282 public int getTotalLineCount() {
283 if (treeRoot
== null) {
286 return getChildren().size();
290 * Get the length of the widest item to display.
292 * @return the maximum number of columns for this item or its children
294 public int getMaximumColumn() {
295 if (treeRoot
== null) {
298 return treeRoot
.getMaximumColumn();
302 * Update the Y positions of all the children items to match the current
303 * topLine value. Note package private access.
306 if (treeRoot
== null) {
310 // As we walk the list we also adjust next/previous pointers,
311 // resulting in a doubly-linked list but only of the expanded items.
314 for (int i
= 0; i
< getChildren().size(); i
++) {
315 TTreeItem item
= (TTreeItem
) getChildren().get(i
);
318 item
.keyboardPrevious
= p
;
319 p
.keyboardNext
= item
;
323 item
.setY(i
- topLine
);
324 item
.setWidth(getWidth());