From 7668cb45fd91775da14504919d8a239af2f7c07e Mon Sep 17 00:00:00 2001 From: Kevin Lamonte Date: Fri, 27 Mar 2015 16:18:05 -0400 Subject: [PATCH] TTreeView compiles --- src/jexer/TDirectoryTreeItem.java | 187 +++++++++++ src/jexer/TTreeItem.java | 418 ++++++++++++++++++++++++ src/jexer/TTreeView.java | 384 ++++++++++++++++++++++ src/jexer/TWidget.java | 49 ++- src/jexer/demos/DemoApplication.java | 2 +- src/jexer/demos/DemoCheckboxWindow.java | 2 +- src/jexer/demos/DemoMainWindow.java | 10 +- src/jexer/demos/DemoMsgBoxWindow.java | 2 +- src/jexer/demos/DemoTextWindow.java | 2 +- src/jexer/demos/DemoTreeViewWindow.java | 81 +++++ 10 files changed, 1124 insertions(+), 13 deletions(-) create mode 100644 src/jexer/TDirectoryTreeItem.java create mode 100644 src/jexer/TTreeItem.java create mode 100644 src/jexer/TTreeView.java create mode 100644 src/jexer/demos/DemoTreeViewWindow.java diff --git a/src/jexer/TDirectoryTreeItem.java b/src/jexer/TDirectoryTreeItem.java new file mode 100644 index 00000000..25a33dfa --- /dev/null +++ b/src/jexer/TDirectoryTreeItem.java @@ -0,0 +1,187 @@ +/** + * 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 parentItems = new LinkedList(); + List parentPaths = new LinkedList(); + 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(); + } +} diff --git a/src/jexer/TTreeItem.java b/src/jexer/TTreeItem.java new file mode 100644 index 00000000..e97ea0eb --- /dev/null +++ b/src/jexer/TTreeItem.java @@ -0,0 +1,418 @@ +/** + * 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 expandTree(final String prefix, final boolean last) { + List array = new ArrayList(); + 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); + } + } + } + +} diff --git a/src/jexer/TTreeView.java b/src/jexer/TTreeView.java new file mode 100644 index 00000000..8c710f3e --- /dev/null +++ b/src/jexer/TTreeView.java @@ -0,0 +1,384 @@ +/** + * 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(); + } + +} diff --git a/src/jexer/TWidget.java b/src/jexer/TWidget.java index 7ea1a427..a32b716a 100644 --- a/src/jexer/TWidget.java +++ b/src/jexer/TWidget.java @@ -370,11 +370,16 @@ public abstract class TWidget implements Comparable { } /** - * Comparison operator sorts on tabOrder for TWidgets and z for TWindows. - * - * @param that another TWidget or TWindow instance + * Comparison operator sorts on: + *
    + *
  • tabOrder for TWidgets
  • + *
  • z for TWindows
  • + *
  • text for TTreeItems
  • + *
+ * + * @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) { @@ -383,6 +388,12 @@ public abstract class TWidget implements Comparable { ) { 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); } @@ -1272,4 +1283,34 @@ public abstract class TWidget implements Comparable { 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); + } + + } diff --git a/src/jexer/demos/DemoApplication.java b/src/jexer/demos/DemoApplication.java index 22609620..4b31c717 100644 --- a/src/jexer/demos/DemoApplication.java +++ b/src/jexer/demos/DemoApplication.java @@ -39,7 +39,7 @@ import jexer.menu.*; /** * The demo application itself. */ -class DemoApplication extends TApplication { +public class DemoApplication extends TApplication { /** * Add all the widgets of the demo. diff --git a/src/jexer/demos/DemoCheckboxWindow.java b/src/jexer/demos/DemoCheckboxWindow.java index 8f92bff3..783ad8bb 100644 --- a/src/jexer/demos/DemoCheckboxWindow.java +++ b/src/jexer/demos/DemoCheckboxWindow.java @@ -38,7 +38,7 @@ import jexer.menu.*; * This window demonstates the TRadioGroup, TRadioButton, and TCheckbox * widgets. */ -class DemoCheckboxWindow extends TWindow { +public class DemoCheckboxWindow extends TWindow { /** * Constructor. diff --git a/src/jexer/demos/DemoMainWindow.java b/src/jexer/demos/DemoMainWindow.java index cff9bbdb..c2f77e80 100644 --- a/src/jexer/demos/DemoMainWindow.java +++ b/src/jexer/demos/DemoMainWindow.java @@ -38,7 +38,7 @@ import jexer.menu.*; * 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; @@ -153,17 +153,17 @@ class DemoMainWindow extends TWindow { } 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); diff --git a/src/jexer/demos/DemoMsgBoxWindow.java b/src/jexer/demos/DemoMsgBoxWindow.java index 25115ea0..e0c7b211 100644 --- a/src/jexer/demos/DemoMsgBoxWindow.java +++ b/src/jexer/demos/DemoMsgBoxWindow.java @@ -37,7 +37,7 @@ import jexer.menu.*; /** * This window demonstates the TMessageBox and TInputBox widgets. */ -class DemoMsgBoxWindow extends TWindow { +public class DemoMsgBoxWindow extends TWindow { /** * Constructor. diff --git a/src/jexer/demos/DemoTextWindow.java b/src/jexer/demos/DemoTextWindow.java index aa68f892..81235cda 100644 --- a/src/jexer/demos/DemoTextWindow.java +++ b/src/jexer/demos/DemoTextWindow.java @@ -37,7 +37,7 @@ import jexer.menu.*; /** * 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. diff --git a/src/jexer/demos/DemoTreeViewWindow.java b/src/jexer/demos/DemoTreeViewWindow.java new file mode 100644 index 00000000..4bd5a388 --- /dev/null +++ b/src/jexer/demos/DemoTreeViewWindow.java @@ -0,0 +1,81 @@ +/* + * 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); + } + } + +} -- 2.27.0