2 * Jexer - Java Text User Interface
4 * License: LGPLv3 or later
6 * This module is licensed under the GNU Lesser General Public License
7 * Version 3. Please see the file "COPYING" in this directory for more
8 * information about the GNU Lesser General Public License Version 3.
10 * Copyright (C) 2015 Kevin Lamonte
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public License
14 * as published by the Free Software Foundation; either version 3 of
15 * the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, see
24 * http://www.gnu.org/licenses/, or write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
33 import java
.util
.ArrayList
;
34 import java
.util
.List
;
36 import jexer
.bits
.CellAttributes
;
37 import jexer
.bits
.GraphicsChars
;
38 import jexer
.event
.TKeypressEvent
;
39 import jexer
.event
.TMouseEvent
;
40 import static jexer
.TKeypress
.*;
43 * TTreeItem is a single item in a tree view.
45 public class TTreeItem
extends TWidget
{
48 * Hang onto reference to my parent TTreeView so I can call its reflow()
49 * when I add a child node.
51 private TTreeView view
;
54 * Get the parent TTreeView.
56 * @return the parent TTreeView
58 public final TTreeView
getTreeView() {
63 * Displayable text for this item.
68 * Get the displayable text for this item.
70 * @return the displayable text for this item
72 public final String
getText() {
77 * Set the displayable text for this item.
79 * @param the displayable text for this item
81 public final void setText(final String text
) {
86 * If true, this item is expanded in the tree view.
88 private boolean expanded
= true;
93 * @return if true, this item is expanded
95 public final boolean isExpanded() {
100 * Set expanded value.
102 * @param expanded new value
104 public final void setExpanded(boolean expanded
) {
105 this.expanded
= expanded
;
109 * If true, this item can be expanded in the tree view.
111 private boolean expandable
= false;
114 * Get expandable value.
116 * @return if true, this item is expandable
118 public final boolean isExpandable() {
123 * Set expandable value.
125 * @param expandable new value
127 public final void setExpandable(boolean expandable
) {
128 this.expandable
= expandable
;
132 * The vertical bars and such along the left side.
134 private String prefix
= "";
137 * Get the vertical bars and such along the left side.
139 * @return the vertical bars and such along the left side
141 public final String
getPrefix() {
146 * Whether or not this item is last in its parent's list of children.
148 private boolean last
= false;
151 * Tree level. Note package private access.
156 * If true, this item will not be drawn.
158 private boolean invisible
= false;
161 * Set invisible value.
163 * @param invisible new value
165 public final void setInvisible(boolean invisible
) {
166 this.invisible
= invisible
;
170 * True means selected.
172 private boolean selected
= false;
175 * Get selected value.
177 * @return if true, this item is selected
179 public final boolean isSelected() {
184 * Set selected value.
186 * @param selected new value
188 public final void setSelected(boolean selected
) {
189 this.selected
= selected
;
193 * True means select-able.
195 private boolean selectable
= true;
198 * Set selectable value.
200 * @param selectable new value
202 public final void setSelectable(boolean selectable
) {
203 this.selectable
= selectable
;
207 * Public constructor.
209 * @param view root TTreeView
210 * @param text text for this item
211 * @param expanded if true, have it expanded immediately
213 public TTreeItem(final TTreeView view
, final String text
,
214 final boolean expanded
) {
216 super(view
, 0, 0, view
.getWidth() - 3, 1);
218 this.expanded
= expanded
;
221 if (view
.getTreeRoot() == null) {
222 view
.setTreeRoot(this, true);
231 * @param text text for this item
232 * @return the new child item
234 public TTreeItem
addChild(final String text
) {
235 return addChild(text
, true);
241 * @param text text for this item
242 * @param expanded if true, have it expanded immediately
243 * @return the new child item
245 public TTreeItem
addChild(final String text
, final boolean expanded
) {
246 TTreeItem item
= new TTreeItem(view
, text
, expanded
);
247 item
.level
= this.level
+ 1;
248 getChildren().add(item
);
254 * Recursively expand the tree into a linear array of items.
256 * @param prefix = vertical bar of parent levels and such that is set on
258 * @param last = if true, this is the "last" leaf node of a tree
259 * @param additional items to add to the array
261 public List
<TTreeItem
> expandTree(final String prefix
, final boolean last
) {
262 List
<TTreeItem
> array
= new ArrayList
<TTreeItem
>();
264 this.prefix
= prefix
;
267 if ((getChildren().size() == 0) || (expanded
== false)) {
271 String newPrefix
= prefix
;
276 newPrefix
+= GraphicsChars
.CP437
[0xB3];
280 for (int i
= 0; i
< getChildren().size(); i
++) {
281 TTreeItem item
= (TTreeItem
) getChildren().get(i
);
282 if (i
== getChildren().size() - 1) {
283 array
.addAll(item
.expandTree(newPrefix
, true));
285 array
.addAll(item
.expandTree(newPrefix
, false));
292 * Get the x spot for the + or - to expand/collapse.
294 * @return column of the expand/collapse button
296 private int getExpanderX() {
297 if ((level
== 0) || (!expandable
)) {
300 return prefix
.length() + 3;
304 * Recursively unselect my or my children.
306 public void unselect() {
307 if (selected
== true) {
309 view
.setSelected(null);
311 for (TWidget widget
: getChildren()) {
312 if (widget
instanceof TTreeItem
) {
313 TTreeItem item
= (TTreeItem
) widget
;
320 * Handle mouse release events.
322 * @param mouse mouse button release event
325 public void onMouseUp(final TMouseEvent mouse
) {
326 if ((mouse
.getX() == (getExpanderX() - view
.hScroller
.getValue()))
327 && (mouse
.getY() == 0)
330 // Flip expanded flag
331 expanded
= !expanded
;
332 if (expanded
== false) {
333 // Unselect children that became invisible
337 // Let subclasses do something with this
339 } else if (mouse
.getY() == 0) {
340 view
.setSelected(this);
344 // Update the screen after any thing has expanded/contracted
349 * Called when this item is expanded or collapsed. this.expanded will be
350 * true if this item was just expanded from a mouse click or keypress.
352 public void onExpand() {
353 // Default: do nothing.
360 * Draw this item to a window.
368 int offset
= -view
.hScroller
.getValue();
370 CellAttributes color
= getTheme().getColor("ttreeview");
371 CellAttributes textColor
= getTheme().getColor("ttreeview");
372 CellAttributes expanderColor
= getTheme().getColor("ttreeview.expandbutton");
373 CellAttributes selectedColor
= getTheme().getColor("ttreeview.selected");
375 if (!getParent().isAbsoluteActive()) {
376 color
= getTheme().getColor("ttreeview.inactive");
377 textColor
= getTheme().getColor("ttreeview.inactive");
381 textColor
= getTheme().getColor("ttreeview.unreadable");
384 // Blank out the background
385 getScreen().hLineXY(0, 0, getWidth(), ' ', color
);
388 String line
= prefix
;
391 line
+= GraphicsChars
.CP437
[0xC0];
393 line
+= GraphicsChars
.CP437
[0xC3];
395 line
+= GraphicsChars
.CP437
[0xC4];
400 getScreen().putStrXY(offset
, 0, line
, color
);
402 getScreen().putStrXY(offset
+ line
.length(), 0, text
,
405 getScreen().putStrXY(offset
+ line
.length(), 0, text
, textColor
);
407 if ((level
> 0) && (expandable
)) {
409 getScreen().putCharXY(offset
+ getExpanderX(), 0, '-',
412 getScreen().putCharXY(offset
+ getExpanderX(), 0, '+',