--- /dev/null
+/**
+ * Jexer - Java Text User Interface
+ *
+ * License: LGPLv3 or later
+ *
+ * This module is licensed under the GNU Lesser General Public License
+ * Version 3. Please see the file "COPYING" in this directory for more
+ * information about the GNU Lesser General Public License Version 3.
+ *
+ * Copyright (C) 2015 Kevin Lamonte
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * http://www.gnu.org/licenses/, or write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.LinkedList;
+
+/**
+ * TDirectoryTreeItem is a single item in a disk directory tree view.
+ */
+public class TDirectoryTreeItem extends TTreeItem {
+
+ /**
+ * Directory entry corresponding to this list item.
+ */
+ File dir;
+
+ /**
+ * Called when this item is expanded or collapsed. this.expanded will be
+ * true if this item was just expanded from a mouse click or keypress.
+ */
+ @Override
+ public void onExpand() {
+ if (dir == null) {
+ return;
+ }
+ getChildren().clear();
+
+ // Make sure we can read it before trying to.
+ if (dir.canRead()) {
+ setSelectable(true);
+ } else {
+ setSelectable(false);
+ }
+ assert (dir.isDirectory());
+ setExpandable(true);
+
+ if ((isExpanded() == false) || (isExpandable() == false)) {
+ getTreeView().reflow();
+ return;
+ }
+
+ // Refresh my child list
+ for (File file: dir.listFiles()) {
+ if (file.getName().equals(".")) {
+ continue;
+ }
+ if (!file.isDirectory()) {
+ continue;
+ }
+
+ TDirectoryTreeItem item = new TDirectoryTreeItem(getTreeView(),
+ file.getName(), false, false);
+
+ item.level = this.level + 1;
+ getChildren().add(item);
+ }
+ Collections.sort(getChildren());
+
+ getTreeView().reflow();
+ }
+
+ /**
+ * Add a child item. This method should never be used, it will throw an
+ * IllegalArgumentException every time.
+ *
+ * @param text text for this item
+ * @param expanded if true, have it expanded immediately
+ * @return the new item
+ * @throws IllegalArgumentException if this function is called
+ */
+ @Override
+ public final TTreeItem addChild(final String text, final boolean expanded) {
+ throw new IllegalArgumentException("Do not call addChild(), use onExpand() instead");
+ }
+
+ /**
+ * Public constructor.
+ *
+ * @param view root TTreeView
+ * @param text text for this item
+ */
+ public TDirectoryTreeItem(final TTreeView view, final String text) {
+ this(view, text, false, true);
+ }
+
+ /**
+ * Public constructor.
+ *
+ * @param view root TTreeView
+ * @param text text for this item
+ * @param expanded if true, have it expanded immediately
+ */
+ public TDirectoryTreeItem(final TTreeView view, final String text,
+ final boolean expanded) {
+
+ this(view, text, expanded, true);
+ }
+
+ /**
+ * Public constructor.
+ *
+ * @param view root TTreeView
+ * @param text text for this item
+ * @param expanded if true, have it expanded immediately
+ * @param openParents if true, expand all paths up the root path and
+ * return the root path entry
+ */
+ public TDirectoryTreeItem(final TTreeView view, final String text,
+ final boolean expanded, final boolean openParents) {
+
+ super(view, text, false);
+
+ List<TDirectoryTreeItem> parentItems = new LinkedList<TDirectoryTreeItem>();
+ List<String> parentPaths = new LinkedList<String>();
+ boolean oldExpanded = expanded;
+
+ if (openParents == true) {
+ setExpanded(true);
+
+ // Go up the directory tree
+ File rootPath = new File(text);
+ File parent = rootPath.getParentFile();
+ while (parent != null) {
+ parentPaths.add(rootPath.getName());
+ rootPath = rootPath.getParentFile();
+ parent = rootPath.getParentFile();
+ }
+ setText(rootPath.getName());
+ } else {
+ setText(text);
+ }
+
+ dir = new File(getText());
+ onExpand();
+
+ if (openParents == true) {
+ TDirectoryTreeItem childPath = this;
+ Collections.reverse(parentPaths);
+ for (String p: parentPaths) {
+ for (TWidget widget: childPath.getChildren()) {
+ TDirectoryTreeItem child = (TDirectoryTreeItem) widget;
+ if (child.getText().equals(p)) {
+ childPath = child;
+ childPath.setExpanded(true);
+ childPath.onExpand();
+ break;
+ }
+ }
+ }
+ unselect();
+ getTreeView().setSelected(childPath);
+ setExpanded(oldExpanded);
+ }
+ getTreeView().reflow();
+ }
+}
--- /dev/null
+/**
+ * Jexer - Java Text User Interface
+ *
+ * License: LGPLv3 or later
+ *
+ * This module is licensed under the GNU Lesser General Public License
+ * Version 3. Please see the file "COPYING" in this directory for more
+ * information about the GNU Lesser General Public License Version 3.
+ *
+ * Copyright (C) 2015 Kevin Lamonte
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * http://www.gnu.org/licenses/, or write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jexer.bits.CellAttributes;
+import jexer.bits.GraphicsChars;
+import jexer.event.TKeypressEvent;
+import jexer.event.TMouseEvent;
+import static jexer.TKeypress.*;
+
+/**
+ * TTreeItem is a single item in a tree view.
+ */
+public class TTreeItem extends TWidget {
+
+ /**
+ * Hang onto reference to my parent TTreeView so I can call its reflow()
+ * when I add a child node.
+ */
+ private TTreeView view;
+
+ /**
+ * Get the parent TTreeView.
+ *
+ * @return the parent TTreeView
+ */
+ public final TTreeView getTreeView() {
+ return view;
+ }
+
+ /**
+ * Displayable text for this item.
+ */
+ private String text;
+
+ /**
+ * Get the displayable text for this item.
+ *
+ * @return the displayable text for this item
+ */
+ public final String getText() {
+ return text;
+ }
+
+ /**
+ * Set the displayable text for this item.
+ *
+ * @param the displayable text for this item
+ */
+ public final void setText(final String text) {
+ this.text = text;
+ }
+
+ /**
+ * If true, this item is expanded in the tree view.
+ */
+ private boolean expanded = true;
+
+ /**
+ * Get expanded value.
+ *
+ * @return if true, this item is expanded
+ */
+ public final boolean isExpanded() {
+ return expanded;
+ }
+
+ /**
+ * Set expanded value.
+ *
+ * @param expanded new value
+ */
+ public final void setExpanded(boolean expanded) {
+ this.expanded = expanded;
+ }
+
+ /**
+ * If true, this item can be expanded in the tree view.
+ */
+ private boolean expandable = false;
+
+ /**
+ * Get expandable value.
+ *
+ * @return if true, this item is expandable
+ */
+ public final boolean isExpandable() {
+ return expandable;
+ }
+
+ /**
+ * Set expandable value.
+ *
+ * @param expandable new value
+ */
+ public final void setExpandable(boolean expandable) {
+ this.expandable = expandable;
+ }
+
+ /**
+ * The vertical bars and such along the left side.
+ */
+ private String prefix = "";
+
+ /**
+ * Get the vertical bars and such along the left side.
+ *
+ * @return the vertical bars and such along the left side
+ */
+ public final String getPrefix() {
+ return prefix;
+ }
+
+ /**
+ * Whether or not this item is last in its parent's list of children.
+ */
+ private boolean last = false;
+
+ /**
+ * Tree level. Note package private access.
+ */
+ int level = 0;
+
+ /**
+ * If true, this item will not be drawn.
+ */
+ private boolean invisible = false;
+
+ /**
+ * Set invisible value.
+ *
+ * @param invisible new value
+ */
+ public final void setInvisible(boolean invisible) {
+ this.invisible = invisible;
+ }
+
+ /**
+ * True means selected.
+ */
+ private boolean selected = false;
+
+ /**
+ * Get selected value.
+ *
+ * @return if true, this item is selected
+ */
+ public final boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * Set selected value.
+ *
+ * @param selected new value
+ */
+ public final void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ /**
+ * True means select-able.
+ */
+ private boolean selectable = true;
+
+ /**
+ * Set selectable value.
+ *
+ * @param selectable new value
+ */
+ public final void setSelectable(boolean selectable) {
+ this.selectable = selectable;
+ }
+
+ /**
+ * Public constructor.
+ *
+ * @param view root TTreeView
+ * @param text text for this item
+ * @param expanded if true, have it expanded immediately
+ */
+ public TTreeItem(final TTreeView view, final String text,
+ final boolean expanded) {
+
+ super(view, 0, 0, view.getWidth() - 3, 1);
+ this.text = text;
+ this.expanded = expanded;
+ this.view = view;
+
+ if (view.getTreeRoot() == null) {
+ view.setTreeRoot(this, true);
+ }
+
+ view.reflow();
+ }
+
+ /**
+ * Add a child item.
+ *
+ * @param text text for this item
+ * @return the new child item
+ */
+ public TTreeItem addChild(final String text) {
+ return addChild(text, true);
+ }
+
+ /**
+ * Add a child item.
+ *
+ * @param text text for this item
+ * @param expanded if true, have it expanded immediately
+ * @return the new child item
+ */
+ public TTreeItem addChild(final String text, final boolean expanded) {
+ TTreeItem item = new TTreeItem(view, text, expanded);
+ item.level = this.level + 1;
+ getChildren().add(item);
+ view.reflow();
+ return item;
+ }
+
+ /**
+ * Recursively expand the tree into a linear array of items.
+ *
+ * @param prefix = vertical bar of parent levels and such that is set on
+ * each child
+ * @param last = if true, this is the "last" leaf node of a tree
+ * @param additional items to add to the array
+ */
+ public List<TTreeItem> expandTree(final String prefix, final boolean last) {
+ List<TTreeItem> array = new ArrayList<TTreeItem>();
+ this.last = last;
+ this.prefix = prefix;
+ array.add(this);
+
+ if ((getChildren().size() == 0) || (expanded == false)) {
+ return array;
+ }
+
+ String newPrefix = prefix;
+ if (level > 0) {
+ if (last) {
+ newPrefix += " ";
+ } else {
+ newPrefix += GraphicsChars.CP437[0xB3];
+ newPrefix += ' ';
+ }
+ }
+ for (int i = 0; i < getChildren().size(); i++) {
+ TTreeItem item = (TTreeItem) getChildren().get(i);
+ if (i == getChildren().size() - 1) {
+ array.addAll(item.expandTree(newPrefix, true));
+ } else {
+ array.addAll(item.expandTree(newPrefix, false));
+ }
+ }
+ return array;
+ }
+
+ /**
+ * Get the x spot for the + or - to expand/collapse.
+ *
+ * @return column of the expand/collapse button
+ */
+ private int getExpanderX() {
+ if ((level == 0) || (!expandable)) {
+ return 0;
+ }
+ return prefix.length() + 3;
+ }
+
+ /**
+ * Recursively unselect my or my children.
+ */
+ public void unselect() {
+ if (selected == true) {
+ selected = false;
+ view.setSelected(null);
+ }
+ for (TWidget widget: getChildren()) {
+ if (widget instanceof TTreeItem) {
+ TTreeItem item = (TTreeItem) widget;
+ item.unselect();
+ }
+ }
+ }
+
+ /**
+ * Handle mouse release events.
+ *
+ * @param mouse mouse button release event
+ */
+ @Override
+ public void onMouseUp(final TMouseEvent mouse) {
+ if ((mouse.getX() == (getExpanderX() - view.hScroller.getValue()))
+ && (mouse.getY() == 0)
+ ) {
+ if (selectable) {
+ // Flip expanded flag
+ expanded = !expanded;
+ if (expanded == false) {
+ // Unselect children that became invisible
+ unselect();
+ }
+ }
+ // Let subclasses do something with this
+ onExpand();
+ } else if (mouse.getY() == 0) {
+ view.setSelected(this);
+ view.dispatch();
+ }
+
+ // Update the screen after any thing has expanded/contracted
+ view.reflow();
+ }
+
+ /**
+ * Called when this item is expanded or collapsed. this.expanded will be
+ * true if this item was just expanded from a mouse click or keypress.
+ */
+ public void onExpand() {
+ // Default: do nothing.
+ if (!expandable) {
+ return;
+ }
+ }
+
+ /**
+ * Draw this item to a window.
+ */
+ @Override
+ public void draw() {
+ if (invisible) {
+ return;
+ }
+
+ int offset = -view.hScroller.getValue();
+
+ CellAttributes color = getTheme().getColor("ttreeview");
+ CellAttributes textColor = getTheme().getColor("ttreeview");
+ CellAttributes expanderColor = getTheme().getColor("ttreeview.expandbutton");
+ CellAttributes selectedColor = getTheme().getColor("ttreeview.selected");
+
+ if (!getParent().isAbsoluteActive()) {
+ color = getTheme().getColor("ttreeview.inactive");
+ textColor = getTheme().getColor("ttreeview.inactive");
+ }
+
+ if (!selectable) {
+ textColor = getTheme().getColor("ttreeview.unreadable");
+ }
+
+ // Blank out the background
+ getScreen().hLineXY(0, 0, getWidth(), ' ', color);
+
+ int expandX = 0;
+ String line = prefix;
+ if (level > 0) {
+ if (last) {
+ line += GraphicsChars.CP437[0xC0];
+ } else {
+ line += GraphicsChars.CP437[0xC3];
+ }
+ line += GraphicsChars.CP437[0xC4];
+ if (expandable) {
+ line += "[ ] ";
+ }
+ }
+ getScreen().putStrXY(offset, 0, line, color);
+ if (selected) {
+ getScreen().putStrXY(offset + line.length(), 0, text,
+ selectedColor);
+ } else {
+ getScreen().putStrXY(offset + line.length(), 0, text, textColor);
+ }
+ if ((level > 0) && (expandable)) {
+ if (expanded) {
+ getScreen().putCharXY(offset + getExpanderX(), 0, '-',
+ expanderColor);
+ } else {
+ getScreen().putCharXY(offset + getExpanderX(), 0, '+',
+ expanderColor);
+ }
+ }
+ }
+
+}
--- /dev/null
+/**
+ * Jexer - Java Text User Interface
+ *
+ * License: LGPLv3 or later
+ *
+ * This module is licensed under the GNU Lesser General Public License
+ * Version 3. Please see the file "COPYING" in this directory for more
+ * information about the GNU Lesser General Public License Version 3.
+ *
+ * Copyright (C) 2015 Kevin Lamonte
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * http://www.gnu.org/licenses/, or write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer;
+
+import jexer.bits.CellAttributes;
+import jexer.bits.GraphicsChars;
+import jexer.event.TKeypressEvent;
+import jexer.event.TMouseEvent;
+import static jexer.TKeypress.*;
+
+/**
+ * TTreeView implements a simple tree view.
+ */
+public class TTreeView extends TWidget {
+
+ /**
+ * Vertical scrollbar.
+ */
+ private TVScroller vScroller;
+
+ /**
+ * Horizontal scrollbar. Note package private access.
+ */
+ THScroller hScroller;
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Maximum width of a single line.
+ */
+ private int maxLineWidth;
+
+ /**
+ * Only one of my children can be selected.
+ */
+ private TTreeItem selectedItem = null;
+
+ /**
+ * If true, move the window to put the selected item in view. This
+ * normally only happens once after setting treeRoot.
+ */
+ public 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
+ */
+ public void setTreeRoot(final TTreeItem treeRoot, final boolean centerWindow) {
+ this.treeRoot = treeRoot;
+ this.centerWindow = centerWindow;
+ }
+
+ /**
+ * Public constructor.
+ *
+ * @param parent parent widget
+ * @param x column relative to parent
+ * @param y row relative to parent
+ * @param width width of tree view
+ * @param height height of tree view
+ */
+ public TTreeView(final TWidget parent, final int x, final int y,
+ final int width, final int height) {
+
+ this(parent, x, y, width, height, null);
+ }
+
+ /**
+ * Public constructor.
+ *
+ * @param parent parent widget
+ * @param x column relative to parent
+ * @param y row relative to parent
+ * @param width width of tree view
+ * @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,
+ final int width, final int height, final TAction action) {
+
+ super(parent, x, y, width, height);
+ this.action = action;
+ }
+
+ /**
+ * 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. Note package private access.
+ *
+ * @param item new item that became selected
+ */
+ 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. Note package private access.
+ */
+ void dispatch() {
+ if (action != null) {
+ action.DO();
+ }
+ }
+
+ /**
+ * Update (or instantiate) vScroller and hScroller.
+ */
+ private void updateScrollers() {
+ // Setup vertical scroller
+ if (vScroller == null) {
+ vScroller = new TVScroller(this, getWidth() - 1, 0,
+ getHeight() - 1);
+ vScroller.setValue(0);
+ vScroller.setTopValue(0);
+ }
+ vScroller.setX(getWidth() - 1);
+ vScroller.setHeight(getHeight() - 1);
+ vScroller.setBigChange(getHeight() - 1);
+
+ // Setup horizontal scroller
+ if (hScroller == null) {
+ hScroller = new THScroller(this, 0, getHeight() - 1,
+ getWidth() - 1);
+ hScroller.setValue(0);
+ hScroller.setLeftValue(0);
+ }
+ hScroller.setY(getHeight() - 1);
+ hScroller.setWidth(getWidth() - 1);
+ hScroller.setBigChange(getWidth() - 1);
+ }
+
+ /**
+ * Resize text and scrollbars for a new width/height.
+ */
+ public void reflow() {
+ int selectedRow = 0;
+ boolean foundSelectedRow = false;
+
+ updateScrollers();
+ 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);
+ }
+ }
+
+ // Expand the tree into a linear list
+ getChildren().clear();
+ getChildren().addAll(treeRoot.expandTree("", true));
+ for (TWidget widget: getChildren()) {
+ TTreeItem item = (TTreeItem) widget;
+
+ if (item == selectedItem) {
+ foundSelectedRow = true;
+ }
+ if (foundSelectedRow == false) {
+ selectedRow++;
+ }
+
+ int lineWidth = item.getText().length()
+ + item.getPrefix().length() + 4;
+ if (lineWidth > maxLineWidth) {
+ maxLineWidth = lineWidth;
+ }
+ }
+ if ((centerWindow) && (foundSelectedRow)) {
+ if ((selectedRow < vScroller.getValue())
+ || (selectedRow > vScroller.getValue() + getHeight() - 2)
+ ) {
+ vScroller.setValue(selectedRow);
+ centerWindow = false;
+ }
+ }
+ updatePositions();
+
+ // Rescale the scroll bars
+ vScroller.setBottomValue(getChildren().size() - getHeight() + 1);
+ if (vScroller.getBottomValue() < 0) {
+ vScroller.setBottomValue(0);
+ }
+ /*
+ if (vScroller.getValue() > vScroller.getBottomValue()) {
+ vScroller.setValue(vScroller.getBottomValue());
+ }
+ */
+ hScroller.setRightValue(maxLineWidth - getWidth() + 3);
+ if (hScroller.getRightValue() < 0) {
+ hScroller.setRightValue(0);
+ }
+ /*
+ if (hScroller.getValue() > hScroller.getRightValue()) {
+ hScroller.setValue(hScroller.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 = vScroller.getValue();
+ int topY = 0;
+ for (int i = 0; i < getChildren().size(); i++) {
+ if (!(getChildren().get(i) instanceof TTreeItem)) {
+ // Skip
+ continue;
+ }
+ TTreeItem item = (TTreeItem) getChildren().get(i);
+
+ 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++;
+ }
+ }
+
+ /**
+ * Handle mouse press events.
+ *
+ * @param mouse mouse button press event
+ */
+ @Override
+ public void onMouseDown(final TMouseEvent mouse) {
+ if (mouse.isMouseWheelUp()) {
+ vScroller.decrement();
+ } else if (mouse.isMouseWheelDown()) {
+ vScroller.increment();
+ } else {
+ // Pass to children
+ super.onMouseDown(mouse);
+ }
+
+ // Update the screen after the scrollbars have moved
+ reflow();
+ }
+
+ /**
+ * Handle mouse release events.
+ *
+ * @param mouse mouse button release event
+ */
+ @Override
+ public void onMouseUp(TMouseEvent mouse) {
+ // Pass to children
+ super.onMouseDown(mouse);
+
+ // Update the screen after any thing has expanded/contracted
+ reflow();
+ }
+
+ /**
+ * Handle keystrokes.
+ *
+ * @param keypress keystroke event
+ */
+ @Override
+ public void onKeypress(final TKeypressEvent keypress) {
+ if (keypress.equals(kbLeft)) {
+ hScroller.decrement();
+ } else if (keypress.equals(kbRight)) {
+ hScroller.increment();
+ } else if (keypress.equals(kbUp)) {
+ vScroller.decrement();
+ } else if (keypress.equals(kbDown)) {
+ vScroller.increment();
+ } else if (keypress.equals(kbPgUp)) {
+ vScroller.bigDecrement();
+ } else if (keypress.equals(kbPgDn)) {
+ vScroller.bigIncrement();
+ } else if (keypress.equals(kbHome)) {
+ vScroller.toTop();
+ } else if (keypress.equals(kbEnd)) {
+ vScroller.toBottom();
+ } else if (keypress.equals(kbEnter)) {
+ if (selectedItem != null) {
+ dispatch();
+ }
+ } else {
+ // Pass other keys (tab etc.) on
+ super.onKeypress(keypress);
+ }
+
+ // Update the screen after any thing has expanded/contracted
+ reflow();
+ }
+
+}
}
/**
- * Comparison operator sorts on tabOrder for TWidgets and z for TWindows.
- *
- * @param that another TWidget or TWindow instance
+ * Comparison operator sorts on:
+ * <ul>
+ * <li>tabOrder for TWidgets</li>
+ * <li>z for TWindows</li>
+ * <li>text for TTreeItems</li>
+ * </ul>
+ *
+ * @param that another TWidget, TWindow, or TTreeItem instance
* @return difference between this.tabOrder and that.tabOrder, or
- * difference between this.z and that.z
+ * difference between this.z and that.z, or String.compareTo(text)
*/
@Override
public final int compareTo(final TWidget that) {
) {
return (((TWindow) this).getZ() - ((TWindow) that).getZ());
}
+ if ((this instanceof TTreeItem)
+ && (that instanceof TTreeItem)
+ ) {
+ return (((TTreeItem) this).getText().compareTo(
+ ((TTreeItem) that).getText()));
+ }
return (this.tabOrder - that.tabOrder);
}
updateAction);
}
+ /**
+ * Convenience function to add a tree view to this container/window.
+ *
+ * @param x column relative to parent
+ * @param y row relative to parent
+ * @param width width of tree view
+ * @param height height of tree view
+ */
+ public final TTreeView addTreeView(final int x, final int y,
+ final int width, final int height) {
+
+ return new TTreeView(this, x, y, width, height);
+ }
+
+ /**
+ * Convenience function to add a tree view to this container/window.
+ *
+ * @param x column relative to parent
+ * @param y row relative to parent
+ * @param width width of tree view
+ * @param height height of tree view
+ * @param action action to perform when an item is selected
+ */
+ public final TTreeView addTreeView(final int x, final int y,
+ final int width, final int height, final TAction action) {
+
+ return new TTreeView(this, x, y, width, height, action);
+ }
+
+
}
/**
* The demo application itself.
*/
-class DemoApplication extends TApplication {
+public class DemoApplication extends TApplication {
/**
* Add all the widgets of the demo.
* This window demonstates the TRadioGroup, TRadioButton, and TCheckbox
* widgets.
*/
-class DemoCheckboxWindow extends TWindow {
+public class DemoCheckboxWindow extends TWindow {
/**
* Constructor.
* This is the main "demo" application window. It makes use of the TTimer,
* TProgressBox, TLabel, TButton, and TField widgets.
*/
-class DemoMainWindow extends TWindow {
+public class DemoMainWindow extends TWindow {
// Timer that increments a number.
private TTimer timer;
}
row += 2;
- /*
if (!isModal()) {
addLabel("Tree views", 1, row);
addButton("Tree&View", 35, row,
- {
- new DemoTreeViewWindow(application);
+ new TAction() {
+ public void DO() {
+ new DemoTreeViewWindow(getApplication());
+ }
}
);
}
row += 2;
- */
if (!isModal()) {
addLabel("Terminal", 1, row);
/**
* This window demonstates the TMessageBox and TInputBox widgets.
*/
-class DemoMsgBoxWindow extends TWindow {
+public class DemoMsgBoxWindow extends TWindow {
/**
* Constructor.
/**
* This window demonstates the TText, THScroller, and TVScroller widgets.
*/
-class DemoTextWindow extends TWindow {
+public class DemoTextWindow extends TWindow {
/**
* Hang onto my TText so I can resize it with the window.
--- /dev/null
+/*
+ * Jexer - Java Text User Interface
+ *
+ * License: LGPLv3 or later
+ *
+ * This module is licensed under the GNU Lesser General Public License
+ * Version 3. Please see the file "COPYING" in this directory for more
+ * information about the GNU Lesser General Public License Version 3.
+ *
+ * Copyright (C) 2015 Kevin Lamonte
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see
+ * http://www.gnu.org/licenses/, or write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer.demos;
+
+import jexer.*;
+import jexer.event.*;
+import jexer.menu.*;
+
+/**
+ * This window demonstates the TTreeView widget.
+ */
+public class DemoTreeViewWindow extends TWindow {
+
+ /**
+ * Hang onto my TTreeView so I can resize it with the window.
+ */
+ private TTreeView treeView;
+
+ /**
+ * Public constructor.
+ *
+ * @param parent the main application
+ */
+ public DemoTreeViewWindow(TApplication parent) {
+ super(parent, "Tree View", 0, 0, 44, 16, TWindow.RESIZABLE);
+
+ // Load the treeview with "stuff"
+ treeView = addTreeView(1, 1, 40, 12);
+ TDirectoryTreeItem root = new TDirectoryTreeItem(treeView, ".", true);
+ }
+
+ /**
+ * Handle window/screen resize events.
+ *
+ * @param resize resize event
+ */
+ @Override
+ public void onResize(TResizeEvent resize) {
+ if (resize.getType() == TResizeEvent.Type.WIDGET) {
+ // Resize the text field
+ treeView.setWidth(resize.getWidth() - 4);
+ treeView.setHeight(resize.getHeight() - 4);
+ treeView.reflow();
+ return;
+ }
+
+ // Pass to children instead
+ for (TWidget widget: getChildren()) {
+ widget.onResize(resize);
+ }
+ }
+
+}