* @author Kevin Lamonte [kevin.lamonte@gmail.com]
* @version 1
*/
-package jexer;
-
+package jexer.ttree;
+
+import jexer.TAction;
+import jexer.THScroller;
+import jexer.TKeypress;
+import jexer.TScrollableWidget;
+import jexer.TVScroller;
+import jexer.TWidget;
import jexer.event.TKeypressEvent;
import jexer.event.TMouseEvent;
import static jexer.TKeypress.*;
/**
- * TTreeView implements a simple tree view.
+ * TTreeViewWidget wraps a tree view with horizontal and vertical scrollbars.
*/
-public class TTreeView extends TScrollableWidget {
-
- /**
- * Root of the tree.
- */
- private TTreeItem treeRoot;
-
- /**
- * Get the root of the tree.
- *
- * @return the root of the tree
- */
- public final TTreeItem getTreeRoot() {
- return treeRoot;
- }
-
- /**
- * Set the root of the tree.
- *
- * @param treeRoot the new root of the tree
- */
- public final void setTreeRoot(final TTreeItem treeRoot) {
- this.treeRoot = treeRoot;
- }
+public class TTreeViewWidget extends TScrollableWidget {
- /**
- * Maximum width of a single line.
- */
- private int maxLineWidth;
+ // ------------------------------------------------------------------------
+ // Variables --------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
- * Only one of my children can be selected.
+ * The TTreeView
*/
- private TTreeItem selectedItem = null;
+ private TTreeView treeView;
/**
* If true, move the window to put the selected item in view. This
private boolean centerWindow = false;
/**
- * The action to perform when the user selects an item.
- */
- private TAction action = null;
-
- /**
- * Set treeRoot.
- *
- * @param treeRoot ultimate root of tree
- * @param centerWindow if true, move the window to put the root in view
+ * Maximum width of a single line.
*/
- public void setTreeRoot(final TTreeItem treeRoot,
- final boolean centerWindow) {
+ private int maxLineWidth;
- this.treeRoot = treeRoot;
- this.centerWindow = centerWindow;
- }
+ // ------------------------------------------------------------------------
+ // Constructors -----------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Public constructor.
* @param width width of tree view
* @param height height of tree view
*/
- public TTreeView(final TWidget parent, final int x, final int y,
+ public TTreeViewWidget(final TWidget parent, final int x, final int y,
final int width, final int height) {
this(parent, x, y, width, height, null);
* @param height height of tree view
* @param action action to perform when an item is selected
*/
- public TTreeView(final TWidget parent, final int x, final int y,
+ public TTreeViewWidget(final TWidget parent, final int x, final int y,
final int width, final int height, final TAction action) {
super(parent, x, y, width, height);
- this.action = action;
+
+ treeView = new TTreeView(this, 0, 0, getWidth() - 1, getHeight() - 1,
+ action);
vScroller = new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
hScroller = new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
- }
-
- /**
- * Get the tree view item that was selected.
- *
- * @return the selected item, or null if no item is selected
- */
- public final TTreeItem getSelected() {
- return selectedItem;
- }
-
- /**
- * Set the new selected tree view item.
- *
- * @param item new item that became selected
- */
- public void setSelected(final TTreeItem item) {
- if (item != null) {
- item.setSelected(true);
- }
- if ((selectedItem != null) && (selectedItem != item)) {
- selectedItem.setSelected(false);
- }
- selectedItem = item;
- }
-
- /**
- * Perform user selection action.
- */
- public void dispatch() {
- if (action != null) {
- action.DO();
- }
- }
- /**
- * Resize text and scrollbars for a new width/height.
- */
- @Override
- public void reflowData() {
- int selectedRow = 0;
- boolean foundSelectedRow = false;
-
- if (treeRoot == null) {
- return;
- }
-
- // Make each child invisible/inactive to start, expandTree() will
- // reactivate the visible ones.
- for (TWidget widget: getChildren()) {
- if (widget instanceof TTreeItem) {
- TTreeItem item = (TTreeItem) widget;
- item.setInvisible(true);
- item.setEnabled(false);
- item.keyboardPrevious = null;
- item.keyboardNext = null;
- }
- }
-
- // Expand the tree into a linear list
- getChildren().clear();
- getChildren().addAll(treeRoot.expandTree("", true));
-
- // Locate the selected row and maximum line width
- for (TWidget widget: getChildren()) {
- TTreeItem item = (TTreeItem) widget;
-
- if (item == selectedItem) {
- foundSelectedRow = true;
- }
- if (!foundSelectedRow) {
- selectedRow++;
- }
-
- int lineWidth = item.getText().length()
- + item.getPrefix().length() + 4;
- if (lineWidth > maxLineWidth) {
- maxLineWidth = lineWidth;
- }
- }
-
- if ((centerWindow) && (foundSelectedRow)) {
- if ((selectedRow < getVerticalValue())
- || (selectedRow > getVerticalValue() + getHeight() - 2)
- ) {
- setVerticalValue(selectedRow);
- centerWindow = false;
- }
- }
- updatePositions();
-
- // Rescale the scroll bars
- setBottomValue(getChildren().size() - getHeight() + 1);
- if (getBottomValue() < 0) {
- setBottomValue(0);
- }
- if (getVerticalValue() > getBottomValue()) {
- setVerticalValue(getBottomValue());
- }
- setRightValue(maxLineWidth - getWidth() + 3);
- if (getRightValue() < 0) {
- setRightValue(0);
- }
- if (getHorizontalValue() > getRightValue()) {
- setHorizontalValue(getRightValue());
- }
- getChildren().add(hScroller);
- getChildren().add(vScroller);
}
- /**
- * Update the Y positions of all the children items.
- */
- private void updatePositions() {
- if (treeRoot == null) {
- return;
- }
-
- int begin = getVerticalValue();
- int topY = 0;
-
- // As we walk the list we also adjust next/previous pointers,
- // resulting in a doubly-linked list but only of the expanded items.
- TTreeItem p = null;
-
- for (int i = 0; i < getChildren().size(); i++) {
- if (!(getChildren().get(i) instanceof TTreeItem)) {
- // Skip the scrollbars
- continue;
- }
- TTreeItem item = (TTreeItem) getChildren().get(i);
-
- if (p != null) {
- item.keyboardPrevious = p;
- p.keyboardNext = item;
- }
- p = item;
-
- if (i < begin) {
- // Render invisible
- item.setEnabled(false);
- item.setInvisible(true);
- continue;
- }
-
- if (topY >= getHeight() - 1) {
- // Render invisible
- item.setEnabled(false);
- item.setInvisible(true);
- continue;
- }
-
- item.setY(topY);
- item.setEnabled(true);
- item.setInvisible(false);
- item.setWidth(getWidth() - 1);
- topY++;
- }
-
- }
+ // ------------------------------------------------------------------------
+ // Event handlers ---------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Handle mouse press events.
} else if (mouse.isMouseWheelDown()) {
verticalIncrement();
} else {
- // Pass to children
+ // Pass to the TreeView or scrollbars
super.onMouseDown(mouse);
}
- // Update the screen after the scrollbars have moved
+ // Update the view to reflect the new scrollbar positions
+ treeView.setTopLine(getVerticalValue());
+ treeView.setLeftColumn(getHorizontalValue());
reflowData();
}
*/
@Override
public void onMouseUp(final TMouseEvent mouse) {
- // Pass to children
- super.onMouseDown(mouse);
+ // Pass to the TreeView or scrollbars
+ super.onMouseUp(mouse);
+
+ // Update the view to reflect the new scrollbar positions
+ treeView.setTopLine(getVerticalValue());
+ treeView.setLeftColumn(getHorizontalValue());
+ reflowData();
+ }
+
+ /**
+ * Handle mouse motion events.
+ *
+ * @param mouse mouse motion event
+ */
+ @Override
+ public void onMouseMotion(final TMouseEvent mouse) {
+ // Pass to the TreeView or scrollbars
+ super.onMouseMotion(mouse);
- // Update the screen after any thing has expanded/contracted
+ // Update the view to reflect the new scrollbar positions
+ treeView.setTopLine(getVerticalValue());
+ treeView.setLeftColumn(getHorizontalValue());
reflowData();
}
|| keypress.equals(kbAltPgDn)
) {
bigVerticalIncrement();
- } else if (keypress.equals(kbHome)) {
- toTop();
- } else if (keypress.equals(kbEnd)) {
- toBottom();
- } else if (keypress.equals(kbEnter)) {
- if (selectedItem != null) {
- dispatch();
+ } else if (keypress.equals(kbPgDn)) {
+ for (int i = 0; i < getHeight() - 2; i++) {
+ treeView.onKeypress(new TKeypressEvent(TKeypress.kbDown));
}
- } else if (keypress.equals(kbUp)) {
- // Select the previous item
- if (selectedItem != null) {
- TTreeItem oldItem = selectedItem;
- if (selectedItem.keyboardPrevious != null) {
- setSelected(selectedItem.keyboardPrevious);
- if (oldItem.getY() == 0) {
- verticalDecrement();
- }
- }
- }
- } else if (keypress.equals(kbDown)) {
- // Select the next item
- if (selectedItem != null) {
- TTreeItem oldItem = selectedItem;
- if (selectedItem.keyboardNext != null) {
- setSelected(selectedItem.keyboardNext);
- if (oldItem.getY() == getHeight() - 2) {
- verticalIncrement();
- }
- }
+ reflowData();
+ return;
+ } else if (keypress.equals(kbPgUp)) {
+ for (int i = 0; i < getHeight() - 2; i++) {
+ treeView.onKeypress(new TKeypressEvent(TKeypress.kbUp));
}
+ reflowData();
+ return;
+ } else if (keypress.equals(kbHome)) {
+ treeView.setSelected((TTreeItem) treeView.getChildren().get(0),
+ false);
+ treeView.setTopLine(0);
+ reflowData();
+ return;
+ } else if (keypress.equals(kbEnd)) {
+ treeView.setSelected((TTreeItem) treeView.getChildren().get(
+ treeView.getChildren().size() - 1), true);
+ reflowData();
+ return;
} else if (keypress.equals(kbTab)) {
getParent().switchWidget(true);
return;
|| keypress.equals(kbBackTab)) {
getParent().switchWidget(false);
return;
- } else if (selectedItem != null) {
- // Give the TTreeItem a chance to handle arrow keys
- selectedItem.onKeypress(keypress);
} else {
- // Pass other keys (tab etc.) on to TWidget's handler.
- super.onKeypress(keypress);
+ treeView.onKeypress(keypress);
+
+ // Update the scrollbars to reflect the new data position
+ reflowData();
return;
}
- // Update the screen after any thing has expanded/contracted
+ // Update the view to reflect the new scrollbar position
+ treeView.setTopLine(getVerticalValue());
+ treeView.setLeftColumn(getHorizontalValue());
reflowData();
}
+ // ------------------------------------------------------------------------
+ // TScrollableWidget ------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Resize text and scrollbars for a new width/height.
+ */
+ @Override
+ public void reflowData() {
+ int selectedRow = 0;
+ boolean foundSelectedRow = false;
+
+ // Reset the keyboard list, expandTree() will recreate it.
+ for (TWidget widget: treeView.getChildren()) {
+ TTreeItem item = (TTreeItem) widget;
+ item.keyboardPrevious = null;
+ item.keyboardNext = null;
+ }
+
+ // Expand the tree into a linear list
+ treeView.getChildren().clear();
+ treeView.getChildren().addAll(treeView.getTreeRoot().expandTree("",
+ true));
+
+ // Locate the selected row and maximum line width
+ for (TWidget widget: treeView.getChildren()) {
+ TTreeItem item = (TTreeItem) widget;
+
+ if (item == treeView.getSelected()) {
+ foundSelectedRow = true;
+ }
+ if (!foundSelectedRow) {
+ selectedRow++;
+ }
+
+ int lineWidth = item.getText().length()
+ + item.getPrefix().length() + 4;
+ if (lineWidth > maxLineWidth) {
+ maxLineWidth = lineWidth;
+ }
+ }
+
+ if ((centerWindow) && (foundSelectedRow)) {
+ if ((selectedRow < getVerticalValue())
+ || (selectedRow > getVerticalValue() + getHeight() - 2)
+ ) {
+ treeView.setTopLine(selectedRow);
+ centerWindow = false;
+ }
+ }
+ treeView.alignTree();
+
+ // Rescale the scroll bars
+ setVerticalValue(treeView.getTopLine());
+ setBottomValue(treeView.getTotalLineCount() - (getHeight() - 1));
+ if (getBottomValue() < getTopValue()) {
+ setBottomValue(getTopValue());
+ }
+ if (getVerticalValue() > getBottomValue()) {
+ setVerticalValue(getBottomValue());
+ }
+ setRightValue(maxLineWidth - 2);
+ if (getHorizontalValue() > getRightValue()) {
+ setHorizontalValue(getRightValue());
+ }
+
+ }
+
+ // ------------------------------------------------------------------------
+ // TTreeView --------------------------------------------------------------
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get the underlying TTreeView.
+ *
+ * @return the TTreeView
+ */
+ public TTreeView getTreeView() {
+ return treeView;
+ }
+
+ /**
+ * Get the root of the tree.
+ *
+ * @return the root of the tree
+ */
+ public final TTreeItem getTreeRoot() {
+ return treeView.getTreeRoot();
+ }
+
+ /**
+ * Set the root of the tree.
+ *
+ * @param treeRoot the new root of the tree
+ */
+ public final void setTreeRoot(final TTreeItem treeRoot) {
+ treeView.setTreeRoot(treeRoot);
+ }
+
+ /**
+ * Set treeRoot.
+ *
+ * @param treeRoot ultimate root of tree
+ * @param centerWindow if true, move the window to put the root in view
+ */
+ public void setTreeRoot(final TTreeItem treeRoot,
+ final boolean centerWindow) {
+
+ treeView.setTreeRoot(treeRoot);
+ this.centerWindow = centerWindow;
+ }
+
+ /**
+ * Get the tree view item that was selected.
+ *
+ * @return the selected item, or null if no item is selected
+ */
+ public final TTreeItem getSelected() {
+ return treeView.getSelected();
+ }
+
+ /**
+ * Set the new selected tree view item.
+ *
+ * @param item new item that became selected
+ * @param centerWindow if true, move the window to put the selected into
+ * view
+ */
+ public void setSelected(final TTreeItem item, final boolean centerWindow) {
+ treeView.setSelected(item, centerWindow);
+ }
+
+ /**
+ * Perform user selection action.
+ */
+ public void dispatch() {
+ treeView.dispatch();
+ }
+
}