X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTTreeView.java;h=b9b05bf0fd492dc0d5b83933a0736d52d7720c55;hb=00fbfc382425d1f20a84cd8897919836cc6254ee;hp=8c710f3e407ef82b6507e8159678661706d0b539;hpb=7668cb45fd91775da14504919d8a239af2f7c07e;p=fanfix.git diff --git a/src/jexer/TTreeView.java b/src/jexer/TTreeView.java index 8c710f3..b9b05bf 100644 --- a/src/jexer/TTreeView.java +++ b/src/jexer/TTreeView.java @@ -1,37 +1,33 @@ -/** +/* * 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. + * The MIT License (MIT) * - * Copyright (C) 2015 Kevin Lamonte + * Copyright (C) 2017 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. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * 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. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * 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 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * * @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.*; @@ -39,17 +35,7 @@ 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; +public class TTreeView extends TScrollableWidget { /** * Root of the tree. @@ -88,7 +74,7 @@ public class TTreeView extends TWidget { * If true, move the window to put the selected item in view. This * normally only happens once after setting treeRoot. */ - public boolean centerWindow = false; + private boolean centerWindow = false; /** * The action to perform when the user selects an item. @@ -101,7 +87,9 @@ public class TTreeView extends TWidget { * @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) { + public void setTreeRoot(final TTreeItem treeRoot, + final boolean centerWindow) { + this.treeRoot = treeRoot; this.centerWindow = centerWindow; } @@ -136,6 +124,9 @@ public class TTreeView extends TWidget { super(parent, x, y, width, height); this.action = action; + + vScroller = new TVScroller(this, getWidth() - 1, 0, getHeight() - 1); + hScroller = new THScroller(this, 0, getHeight() - 1, getWidth() - 1); } /** @@ -148,11 +139,11 @@ public class TTreeView extends TWidget { } /** - * Set the new selected tree view item. Note package private access. + * Set the new selected tree view item. * * @param item new item that became selected */ - void setSelected(final TTreeItem item) { + public void setSelected(final TTreeItem item) { if (item != null) { item.setSelected(true); } @@ -163,49 +154,22 @@ public class TTreeView extends TWidget { } /** - * Perform user selection action. Note package private access. + * Perform user selection action. */ - void dispatch() { + public 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() { + @Override + public void reflowData() { int selectedRow = 0; boolean foundSelectedRow = false; - updateScrollers(); if (treeRoot == null) { return; } @@ -217,57 +181,58 @@ public class TTreeView extends TWidget { 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 == false) { + if (!foundSelectedRow) { selectedRow++; } int lineWidth = item.getText().length() - + item.getPrefix().length() + 4; + + item.getPrefix().length() + 4; if (lineWidth > maxLineWidth) { maxLineWidth = lineWidth; } } + if ((centerWindow) && (foundSelectedRow)) { - if ((selectedRow < vScroller.getValue()) - || (selectedRow > vScroller.getValue() + getHeight() - 2) + if ((selectedRow < getVerticalValue()) + || (selectedRow > getVerticalValue() + getHeight() - 2) ) { - vScroller.setValue(selectedRow); + setVerticalValue(selectedRow); centerWindow = false; } } updatePositions(); // Rescale the scroll bars - vScroller.setBottomValue(getChildren().size() - getHeight() + 1); - if (vScroller.getBottomValue() < 0) { - vScroller.setBottomValue(0); + setBottomValue(getChildren().size() - getHeight() + 1); + if (getBottomValue() < 0) { + setBottomValue(0); } - /* - if (vScroller.getValue() > vScroller.getBottomValue()) { - vScroller.setValue(vScroller.getBottomValue()); + if (getVerticalValue() > getBottomValue()) { + setVerticalValue(getBottomValue()); } - */ - hScroller.setRightValue(maxLineWidth - getWidth() + 3); - if (hScroller.getRightValue() < 0) { - hScroller.setRightValue(0); + setRightValue(maxLineWidth - getWidth() + 3); + if (getRightValue() < 0) { + setRightValue(0); } - /* - if (hScroller.getValue() > hScroller.getRightValue()) { - hScroller.setValue(hScroller.getRightValue()); + if (getHorizontalValue() > getRightValue()) { + setHorizontalValue(getRightValue()); } - */ getChildren().add(hScroller); getChildren().add(vScroller); } @@ -280,15 +245,26 @@ public class TTreeView extends TWidget { return; } - int begin = vScroller.getValue(); + 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 + // 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); @@ -309,6 +285,7 @@ public class TTreeView extends TWidget { item.setWidth(getWidth() - 1); topY++; } + } /** @@ -319,16 +296,16 @@ public class TTreeView extends TWidget { @Override public void onMouseDown(final TMouseEvent mouse) { if (mouse.isMouseWheelUp()) { - vScroller.decrement(); + verticalDecrement(); } else if (mouse.isMouseWheelDown()) { - vScroller.increment(); + verticalIncrement(); } else { // Pass to children super.onMouseDown(mouse); } // Update the screen after the scrollbars have moved - reflow(); + reflowData(); } /** @@ -337,12 +314,12 @@ public class TTreeView extends TWidget { * @param mouse mouse button release event */ @Override - public void onMouseUp(TMouseEvent mouse) { + public void onMouseUp(final TMouseEvent mouse) { // Pass to children super.onMouseDown(mouse); // Update the screen after any thing has expanded/contracted - reflow(); + reflowData(); } /** @@ -352,33 +329,84 @@ public class TTreeView extends TWidget { */ @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(); + if (keypress.equals(kbShiftLeft) + || keypress.equals(kbCtrlLeft) + || keypress.equals(kbAltLeft) + ) { + horizontalDecrement(); + } else if (keypress.equals(kbShiftRight) + || keypress.equals(kbCtrlRight) + || keypress.equals(kbAltRight) + ) { + horizontalIncrement(); + } else if (keypress.equals(kbShiftUp) + || keypress.equals(kbCtrlUp) + || keypress.equals(kbAltUp) + ) { + verticalDecrement(); + } else if (keypress.equals(kbShiftDown) + || keypress.equals(kbCtrlDown) + || keypress.equals(kbAltDown) + ) { + verticalIncrement(); + } else if (keypress.equals(kbShiftPgUp) + || keypress.equals(kbCtrlPgUp) + || keypress.equals(kbAltPgUp) + ) { + bigVerticalDecrement(); + } else if (keypress.equals(kbShiftPgDn) + || keypress.equals(kbCtrlPgDn) + || keypress.equals(kbAltPgDn) + ) { + bigVerticalIncrement(); } else if (keypress.equals(kbHome)) { - vScroller.toTop(); + toTop(); } else if (keypress.equals(kbEnd)) { - vScroller.toBottom(); + toBottom(); } else if (keypress.equals(kbEnter)) { if (selectedItem != null) { dispatch(); } + } 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(); + } + } + } + } else if (keypress.equals(kbTab)) { + getParent().switchWidget(true); + return; + } else if (keypress.equals(kbShiftTab) + || 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 + // Pass other keys (tab etc.) on to TWidget's handler. super.onKeypress(keypress); + return; } // Update the screen after any thing has expanded/contracted - reflow(); + reflowData(); } }