/** * 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.ArrayList; import java.util.List; import jexer.bits.CellAttributes; import jexer.event.TKeypressEvent; import jexer.event.TMouseEvent; import static jexer.TKeypress.*; /** * TDirectoryList shows the files within a directory. */ public class TDirectoryList extends TWidget { /** * Files in the directory. */ private List files; /** * Selected file. */ private int selectedFile = -1; /** * Root path containing files to display. */ public File path; /** * Vertical scrollbar. */ private TVScroller vScroller; /** * Horizontal scrollbar. */ private THScroller hScroller; /** * Maximum width of a single line. */ private int maxLineWidth; /** * The action to perform when the user selects an item. */ private TAction action = null; /** * Perform user selection action. */ public void dispatch() { assert (selectedFile >= 0); assert (selectedFile < files.size()); if (action != null) { action.DO(); } } /** * Format one of the entries for drawing on the screen. * * @param index index into files * @return the line to draw */ private String renderFile(int index) { File file = files.get(index); String name = file.getName(); if (name.length() > 20) { name = name.substring(0, 17) + "..."; } return String.format("%-20s %5dk", name, (file.length() / 1024)); } /** * Resize for a new width/height. */ public void reflow() { // Reset the lines selectedFile = -1; maxLineWidth = 0; files.clear(); // Build a list of files in this directory File [] newFiles = path.listFiles(); for (int i = 0; i < newFiles.length; i++) { if (newFiles[i].getName().startsWith(".")) { continue; } if (newFiles[i].isDirectory()) { continue; } files.add(newFiles[i]); } for (int i = 0; i < files.size(); i++) { String line = renderFile(i); if (line.length() > maxLineWidth) { maxLineWidth = line.length(); } } // Start at the top if (vScroller == null) { vScroller = new TVScroller(this, getWidth() - 1, 0, getHeight() - 1); } else { vScroller.setX(getWidth() - 1); vScroller.setHeight(getHeight() - 1); } vScroller.setBottomValue(files.size() - getHeight() - 1); vScroller.setTopValue(0); vScroller.setValue(0); if (vScroller.getBottomValue() < 0) { vScroller.setBottomValue(0); } vScroller.setBigChange(getHeight() - 1); // Start at the left if (hScroller == null) { hScroller = new THScroller(this, 0, getHeight() - 1, getWidth() - 1); } else { hScroller.setY(getHeight() - 1); hScroller.setWidth(getWidth() - 1); } hScroller.setRightValue(maxLineWidth - getWidth() + 1); hScroller.setLeftValue(0); hScroller.setValue(0); if (hScroller.getRightValue() < 0) { hScroller.setRightValue(0); } hScroller.setBigChange(getWidth() - 1); } /** * Public constructor. * * @param parent parent widget * @param path directory path, must be a directory * @param x column relative to parent * @param y row relative to parent * @param width width of text area * @param height height of text area */ public TDirectoryList(final TWidget parent, final String path, final int x, final int y, final int width, final int height) { this(parent, path, x, y, width, height, null); } /** * Public constructor. * * @param parent parent widget * @param path directory path, must be a directory * @param x column relative to parent * @param y row relative to parent * @param width width of text area * @param height height of text area * @param action action to perform when an item is selected */ public TDirectoryList(final TWidget parent, final String path, final int x, final int y, final int width, final int height, final TAction action) { this.path = new File(path); this.action = action; files = new ArrayList(); reflow(); } /** * Draw the files list. */ @Override public void draw() { CellAttributes color = null; int begin = vScroller.getValue(); int topY = 0; for (int i = begin; i < files.size() - 1; i++) { String line = renderFile(i); if (hScroller.getValue() < line.length()) { line = line.substring(hScroller.getValue()); } else { line = ""; } if (i == selectedFile) { color = getTheme().getColor("tdirectorylist.selected"); } else if (isAbsoluteActive()) { color = getTheme().getColor("tdirectorylist"); } else { color = getTheme().getColor("tdirectorylist.inactive"); } String formatString = "%-" + Integer.toString(getWidth() - 1) + "s"; getScreen().putStringXY(0, topY, String.format(formatString, line), color); topY++; if (topY >= getHeight() - 1) { break; } } // Pad the rest with blank lines for (int i = topY; i < getHeight() - 1; i++) { getScreen().hLineXY(0, i, getWidth() - 1, ' ', color); } } /** * Handle mouse press events. * * @param mouse mouse button press event */ @Override public void onMouseDown(final TMouseEvent mouse) { if (mouse.isMouseWheelUp()) { vScroller.decrement(); return; } if (mouse.isMouseWheelDown()) { vScroller.increment(); return; } if ((mouse.getX() < getWidth() - 1) && (mouse.getY() < getHeight() - 1)) { if (vScroller.getValue() + mouse.getY() < files.size()) { selectedFile = vScroller.getValue() + mouse.getY(); } path = files.get(selectedFile); dispatch(); return; } // Pass to children super.onMouseDown(mouse); } /** * Handle mouse release events. * * @param mouse mouse button release event */ @Override public void onMouseUp(final TMouseEvent mouse) { // Pass to children super.onMouseDown(mouse); } /** * 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 { // Pass other keys (tab etc.) on super.onKeypress(keypress); } } }