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
.TApplication
;
33 import jexer
.THScroller
;
34 import jexer
.TScrollableWindow
;
35 import jexer
.TVScroller
;
37 import jexer
.bits
.StringUtils
;
38 import jexer
.event
.TKeypressEvent
;
39 import jexer
.event
.TMouseEvent
;
40 import jexer
.event
.TResizeEvent
;
41 import static jexer
.TKeypress
.*;
44 * TTreeViewWindow wraps a tree view with horizontal and vertical scrollbars
45 * in a standalone window.
47 public class TTreeViewWindow
extends TScrollableWindow
{
49 // ------------------------------------------------------------------------
50 // Variables --------------------------------------------------------------
51 // ------------------------------------------------------------------------
56 private TTreeView treeView
;
59 * If true, move the window to put the selected item in view. This
60 * normally only happens once after setting treeRoot.
62 private boolean centerWindow
= false;
65 * Maximum width of a single line.
67 private int maxLineWidth
;
69 // ------------------------------------------------------------------------
70 // Constructors -----------------------------------------------------------
71 // ------------------------------------------------------------------------
76 * @param parent the main application
77 * @param title the window title
78 * @param x column relative to parent
79 * @param y row relative to parent
80 * @param width width of tree view
81 * @param flags bitmask of RESIZABLE, CENTERED, or MODAL
82 * @param height height of tree view
84 public TTreeViewWindow(final TApplication parent
, final String title
,
85 final int x
, final int y
, final int width
, final int height
,
88 this(parent
, title
, x
, y
, width
, height
, flags
, null);
94 * @param parent the main application
95 * @param title the window title
96 * @param x column relative to parent
97 * @param y row relative to parent
98 * @param width width of tree view
99 * @param height height of tree view
100 * @param flags bitmask of RESIZABLE, CENTERED, or MODAL
101 * @param action action to perform when an item is selected
103 public TTreeViewWindow(final TApplication parent
, final String title
,
104 final int x
, final int y
, final int width
, final int height
,
105 final int flags
, final TAction action
) {
107 super(parent
, title
, x
, y
, width
, height
, flags
);
109 treeView
= new TTreeView(this, 0, 0, getWidth() - 2, getHeight() - 2,
112 hScroller
= new THScroller(this, 17, getHeight() - 2, getWidth() - 20);
113 vScroller
= new TVScroller(this, getWidth() - 2, 0, getHeight() - 2);
116 System.err.println("TTreeViewWindow()");
117 for (TWidget w: getChildren()) {
118 System.err.println(" " + w + " " + w.isActive());
123 // ------------------------------------------------------------------------
124 // Event handlers ---------------------------------------------------------
125 // ------------------------------------------------------------------------
128 * Handle mouse press events.
130 * @param mouse mouse button press event
133 public void onMouseDown(final TMouseEvent mouse
) {
134 if (mouse
.isMouseWheelUp()) {
136 } else if (mouse
.isMouseWheelDown()) {
139 // Pass to the TreeView or scrollbars
140 super.onMouseDown(mouse
);
143 // Update the view to reflect the new scrollbar positions
144 treeView
.setTopLine(getVerticalValue());
145 treeView
.setLeftColumn(getHorizontalValue());
150 * Handle mouse release events.
152 * @param mouse mouse button release event
155 public void onMouseUp(final TMouseEvent mouse
) {
156 // Pass to the TreeView or scrollbars
157 super.onMouseUp(mouse
);
159 // Update the view to reflect the new scrollbar positions
160 treeView
.setTopLine(getVerticalValue());
161 treeView
.setLeftColumn(getHorizontalValue());
166 * Handle mouse motion events.
168 * @param mouse mouse motion event
171 public void onMouseMotion(final TMouseEvent mouse
) {
172 // Pass to the TreeView or scrollbars
173 super.onMouseMotion(mouse
);
175 // Update the view to reflect the new scrollbar positions
176 treeView
.setTopLine(getVerticalValue());
177 treeView
.setLeftColumn(getHorizontalValue());
184 * @param keypress keystroke event
187 public void onKeypress(final TKeypressEvent keypress
) {
188 if (inKeyboardResize
) {
189 // Let TWindow do its job.
190 super.onKeypress(keypress
);
194 // Give the shortcut bar a shot at this.
195 if (statusBar
!= null) {
196 if (statusBar
.statusBarKeypress(keypress
)) {
201 if (keypress
.equals(kbShiftLeft
)
202 || keypress
.equals(kbCtrlLeft
)
203 || keypress
.equals(kbAltLeft
)
205 horizontalDecrement();
206 } else if (keypress
.equals(kbShiftRight
)
207 || keypress
.equals(kbCtrlRight
)
208 || keypress
.equals(kbAltRight
)
210 horizontalIncrement();
211 } else if (keypress
.equals(kbShiftUp
)
212 || keypress
.equals(kbCtrlUp
)
213 || keypress
.equals(kbAltUp
)
216 } else if (keypress
.equals(kbShiftDown
)
217 || keypress
.equals(kbCtrlDown
)
218 || keypress
.equals(kbAltDown
)
221 } else if (keypress
.equals(kbShiftPgUp
)
222 || keypress
.equals(kbCtrlPgUp
)
223 || keypress
.equals(kbAltPgUp
)
225 bigVerticalDecrement();
226 } else if (keypress
.equals(kbShiftPgDn
)
227 || keypress
.equals(kbCtrlPgDn
)
228 || keypress
.equals(kbAltPgDn
)
230 bigVerticalIncrement();
232 treeView
.onKeypress(keypress
);
234 // Update the scrollbars to reflect the new data position
239 // Update the view to reflect the new scrollbar position
240 treeView
.setTopLine(getVerticalValue());
241 treeView
.setLeftColumn(getHorizontalValue());
245 // ------------------------------------------------------------------------
246 // TScrollableWindow ------------------------------------------------------
247 // ------------------------------------------------------------------------
250 * Handle window/screen resize events.
252 * @param resize resize event
255 public void onResize(final TResizeEvent resize
) {
256 if (resize
.getType() == TResizeEvent
.Type
.WIDGET
) {
257 // Resize the treeView field.
258 TResizeEvent treeSize
= new TResizeEvent(TResizeEvent
.Type
.WIDGET
,
259 resize
.getWidth() - 2, resize
.getHeight() - 2);
260 treeView
.onResize(treeSize
);
262 // Have TScrollableWindow handle the scrollbars.
263 super.onResize(resize
);
265 // Now re-center the treeView field.
266 if (treeView
.getSelected() != null) {
267 treeView
.setSelected(treeView
.getSelected(), true);
275 * Resize text and scrollbars for a new width/height.
278 public void reflowData() {
280 boolean foundSelectedRow
= false;
282 // Reset the keyboard list, expandTree() will recreate it.
283 for (TWidget widget
: treeView
.getChildren()) {
284 TTreeItem item
= (TTreeItem
) widget
;
285 item
.keyboardPrevious
= null;
286 item
.keyboardNext
= null;
289 // Expand the tree into a linear list
290 treeView
.getChildren().clear();
291 treeView
.getChildren().addAll(treeView
.getTreeRoot().expandTree("",
294 // Locate the selected row and maximum line width
295 for (TWidget widget
: treeView
.getChildren()) {
296 TTreeItem item
= (TTreeItem
) widget
;
298 if (item
== treeView
.getSelected()) {
299 foundSelectedRow
= true;
301 if (!foundSelectedRow
) {
305 int lineWidth
= StringUtils
.width(item
.getText())
306 + item
.getPrefix().length() + 4;
307 if (lineWidth
> maxLineWidth
) {
308 maxLineWidth
= lineWidth
;
312 if ((centerWindow
) && (foundSelectedRow
)) {
313 if ((selectedRow
< getVerticalValue())
314 || (selectedRow
> getVerticalValue() + getHeight() - 3)
316 treeView
.setTopLine(selectedRow
);
317 centerWindow
= false;
320 treeView
.alignTree();
322 // Rescale the scroll bars
323 setVerticalValue(treeView
.getTopLine());
324 setBottomValue(treeView
.getTotalLineCount() - (getHeight() - 2));
325 if (getBottomValue() < getTopValue()) {
326 setBottomValue(getTopValue());
328 if (getVerticalValue() > getBottomValue()) {
329 setVerticalValue(getBottomValue());
331 setRightValue(maxLineWidth
- 4);
332 if (getHorizontalValue() > getRightValue()) {
333 setHorizontalValue(getRightValue());
337 // ------------------------------------------------------------------------
338 // TTreeView --------------------------------------------------------------
339 // ------------------------------------------------------------------------
342 * Get the underlying TTreeView.
344 * @return the TTreeView
346 public TTreeView
getTreeView() {
351 * Get the root of the tree.
353 * @return the root of the tree
355 public final TTreeItem
getTreeRoot() {
356 return treeView
.getTreeRoot();
360 * Set the root of the tree.
362 * @param treeRoot the new root of the tree
364 public final void setTreeRoot(final TTreeItem treeRoot
) {
365 treeView
.setTreeRoot(treeRoot
);
371 * @param treeRoot ultimate root of tree
372 * @param centerWindow if true, move the window to put the root in view
374 public void setTreeRoot(final TTreeItem treeRoot
,
375 final boolean centerWindow
) {
377 treeView
.setTreeRoot(treeRoot
);
378 this.centerWindow
= centerWindow
;
382 * Get the tree view item that was selected.
384 * @return the selected item, or null if no item is selected
386 public final TTreeItem
getSelected() {
387 return treeView
.getSelected();
391 * Set the new selected tree view item.
393 * @param item new item that became selected
394 * @param centerWindow if true, move the window to put the selected into
397 public void setSelected(final TTreeItem item
, final boolean centerWindow
) {
398 treeView
.setSelected(item
, centerWindow
);
402 * Perform user selection action.
404 public void dispatch() {