TFileOpenBox working
authorKevin Lamonte <kevin.lamonte@gmail.com>
Sun, 29 Mar 2015 01:30:40 +0000 (21:30 -0400)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Sun, 29 Mar 2015 01:30:40 +0000 (21:30 -0400)
README.md
src/jexer/TApplication.java
src/jexer/TDirectoryList.java
src/jexer/TDirectoryTreeItem.java
src/jexer/TField.java
src/jexer/TFileOpenBox.java
src/jexer/TTreeItem.java
src/jexer/TTreeView.java
src/jexer/TWidget.java
src/jexer/demos/DemoApplication.java
src/jexer/demos/DemoTextWindow.java

index 693e278ac79ef146f6d787b1fc741cd91653b37b..be52f13b5ac2e3238878fe7e40c73f78bcc22951 100644 (file)
--- a/README.md
+++ b/README.md
@@ -175,11 +175,6 @@ Many tasks remain before calling this version 1.0:
 
 0.0.3: FINISH PORTING
 
-- TDirectoryList
-  - Also add keyboard navigation
-- TFileOpen
-  - Also add keyboard navigation
-
 0.0.4: NEW STUFF
 
 - Making TMenu keyboard accelerators active/inactive
index d0c34bf0303adbe99e917f6afbcd278032915af6..1b928dd8442dae3e851a64e91bc8bbd8ee115b4f 100644 (file)
@@ -980,7 +980,8 @@ public class TApplication implements Runnable {
     public final void enableSecondaryEventReceiver(final TWidget widget) {
         assert (secondaryEventReceiver == null);
         assert (secondaryEventHandler == null);
-        assert (widget instanceof TMessageBox);
+        assert ((widget instanceof TMessageBox)
+            || (widget instanceof TFileOpenBox));
         secondaryEventReceiver = widget;
         secondaryEventHandler = new WidgetEventHandler(this, false);
         (new Thread(secondaryEventHandler)).start();
index 3a09bf38bc74dc1dda026f4089dde593fee94a32..563d008eedb2b6dab5c7f3b9b998ab9e7fc77b93 100644 (file)
@@ -42,7 +42,7 @@ import static jexer.TKeypress.*;
 /**
  * TDirectoryList shows the files within a directory.
  */
-public class TDirectoryList extends TWidget {
+public final class TDirectoryList extends TWidget {
 
     /**
      * Files in the directory.
@@ -57,7 +57,26 @@ public class TDirectoryList extends TWidget {
     /**
      * Root path containing files to display.
      */
-    public File path;
+    private File path;
+
+    /**
+     * Set the new path to display.
+     *
+     * @param path new path to list files for
+     */
+    public void setPath(String path) {
+        this.path = new File(path);
+        reflow();
+    }
+
+    /**
+     * Get the path that is being displayed.
+     *
+     * @return the path
+     */
+    public File getPath() {
+        return path;
+    }
 
     /**
      * Vertical scrollbar.
@@ -117,14 +136,16 @@ public class TDirectoryList extends TWidget {
 
         // 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 != null) {
+            for (int i = 0; i < newFiles.length; i++) {
+                if (newFiles[i].getName().startsWith(".")) {
+                    continue;
+                }
+                if (newFiles[i].isDirectory()) {
+                    continue;
+                }
+                files.add(newFiles[i]);
             }
-            if (newFiles[i].isDirectory()) {
-                continue;
-            }
-            files.add(newFiles[i]);
         }
 
         for (int i = 0; i < files.size(); i++) {
@@ -197,6 +218,7 @@ public class TDirectoryList extends TWidget {
     public TDirectoryList(final TWidget parent, final String path, final int x,
         final int y, final int width, final int height, final TAction action) {
 
+        super(parent, x, y, width, height);
         this.path   = new File(path);
         this.action = action;
         files = new ArrayList<File>();
@@ -211,7 +233,7 @@ public class TDirectoryList extends TWidget {
         CellAttributes color = null;
         int begin = vScroller.getValue();
         int topY = 0;
-        for (int i = begin; i < files.size() - 1; i++) {
+        for (int i = begin; i < files.size(); i++) {
             String line = renderFile(i);
             if (hScroller.getValue() < line.length()) {
                 line = line.substring(hScroller.getValue());
@@ -234,6 +256,12 @@ public class TDirectoryList extends TWidget {
             }
         }
 
+        if (isAbsoluteActive()) {
+            color = getTheme().getColor("tdirectorylist");
+        } else {
+            color = getTheme().getColor("tdirectorylist.inactive");
+        }
+
         // Pad the rest with blank lines
         for (int i = topY; i < getHeight() - 1; i++) {
             getScreen().hLineXY(0, i, getWidth() - 1, ' ', color);
@@ -293,17 +321,52 @@ public class TDirectoryList extends TWidget {
         } else if (keypress.equals(kbRight)) {
             hScroller.increment();
         } else if (keypress.equals(kbUp)) {
-            vScroller.decrement();
+            if (files.size() > 0) {
+                if (selectedFile >= 0) {
+                    if (selectedFile > 0) {
+                        selectedFile--;
+                    }
+                } else {
+                    selectedFile = files.size() - 1;
+                }
+                path = files.get(selectedFile);
+            }
         } else if (keypress.equals(kbDown)) {
-            vScroller.increment();
+            if (files.size() > 0) {
+                if (selectedFile >= 0) {
+                    if (selectedFile < files.size() - 1) {
+                        selectedFile++;
+                    }
+                } else {
+                    selectedFile = 0;
+                }
+                path = files.get(selectedFile);
+            }
         } else if (keypress.equals(kbPgUp)) {
             vScroller.bigDecrement();
         } else if (keypress.equals(kbPgDn)) {
             vScroller.bigIncrement();
         } else if (keypress.equals(kbHome)) {
             vScroller.toTop();
+            if (files.size() > 0) {
+                selectedFile = 0;
+                path = files.get(selectedFile);
+            }
         } else if (keypress.equals(kbEnd)) {
             vScroller.toBottom();
+            if (files.size() > 0) {
+                selectedFile = files.size() - 1;
+                path = files.get(selectedFile);
+            }
+        } else if (keypress.equals(kbTab)) {
+            getParent().switchWidget(true);
+        } else if (keypress.equals(kbShiftTab) || keypress.equals(kbBackTab)) {
+            getParent().switchWidget(false);
+        } else if (keypress.equals(kbEnter)) {
+            if (selectedFile >= 0) {
+                path = files.get(selectedFile);
+                dispatch();
+            }
         } else {
             // Pass other keys (tab etc.) on
             super.onKeypress(keypress);
index 01c9b46a4170dad07854cc65898d46e80511d712..1bb30f1d61ef3365f8ccb8028fe37283d1d78d6d 100644 (file)
@@ -42,9 +42,18 @@ import java.util.LinkedList;
 public class TDirectoryTreeItem extends TTreeItem {
 
     /**
-     * Directory entry corresponding to this list item.
+     * File corresponding to this list item.
      */
-    File dir;
+    private File file;
+
+    /**
+     * Get the File corresponding to this list item.
+     *
+     * @return the File
+     */
+    public final File getFile() {
+        return file;
+    }
 
     /**
      * Called when this item is expanded or collapsed.  this.expanded will be
@@ -52,20 +61,20 @@ public class TDirectoryTreeItem extends TTreeItem {
      */
     @Override
     public void onExpand() {
-        // System.err.printf("onExpand() %s\n", dir);
+        // System.err.printf("onExpand() %s\n", file);
 
-        if (dir == null) {
+        if (file == null) {
             return;
         }
         getChildren().clear();
 
         // Make sure we can read it before trying to.
-        if (dir.canRead()) {
+        if (file.canRead()) {
             setSelectable(true);
         } else {
             setSelectable(false);
         }
-        assert (dir.isDirectory());
+        assert (file.isDirectory());
         setExpandable(true);
 
         if ((isExpanded() == false) || (isExpandable() == false)) {
@@ -73,20 +82,20 @@ public class TDirectoryTreeItem extends TTreeItem {
             return;
         }
 
-        for (File file: dir.listFiles()) {
+        for (File f: file.listFiles()) {
             // System.err.printf("   -> file %s %s\n", file, file.getName());
 
-            if (file.getName().startsWith(".")) {
+            if (f.getName().startsWith(".")) {
                 // Hide dot-files
                 continue;
             }
-            if (!file.isDirectory()) {
+            if (!f.isDirectory()) {
                 continue;
             }
 
             try {
                 TDirectoryTreeItem item = new TDirectoryTreeItem(getTreeView(),
-                    file.getCanonicalPath(), false, false);
+                    f.getCanonicalPath(), false, false);
 
                 item.level = this.level + 1;
                 getChildren().add(item);
@@ -152,52 +161,52 @@ public class TDirectoryTreeItem extends TTreeItem {
 
         super(view, text, false);
 
-        List<String> parentPaths = new LinkedList<String>();
+        List<String> parentFiles = new LinkedList<String>();
         boolean oldExpanded = expanded;
 
         // Convert to canonical path
-        File rootPath = new File(text);
-        rootPath = rootPath.getCanonicalFile();
+        File rootFile = new File(text);
+        rootFile = rootFile.getCanonicalFile();
 
         if (openParents == true) {
             setExpanded(true);
 
             // Go up the directory tree
-            File parent = rootPath.getParentFile();
+            File parent = rootFile.getParentFile();
             while (parent != null) {
-                parentPaths.add(rootPath.getName());
-                rootPath = rootPath.getParentFile();
-                parent = rootPath.getParentFile();
+                parentFiles.add(rootFile.getName());
+                rootFile = rootFile.getParentFile();
+                parent = rootFile.getParentFile();
             }
         }
-        dir = rootPath;
-        if (rootPath.getParentFile() == null) {
+        file = rootFile;
+        if (rootFile.getParentFile() == null) {
             // This is a filesystem root, use its full name
-            setText(rootPath.getCanonicalPath());
+            setText(rootFile.getCanonicalPath());
         } else {
             // This is a relative path.  We got here because openParents was
             // false.
             assert (openParents == false);
-            setText(rootPath.getName());
+            setText(rootFile.getName());
         }
         onExpand();
 
         if (openParents == true) {
-            TDirectoryTreeItem childPath = this;
-            Collections.reverse(parentPaths);
-            for (String p: parentPaths) {
-                for (TWidget widget: childPath.getChildren()) {
+            TDirectoryTreeItem childFile = this;
+            Collections.reverse(parentFiles);
+            for (String p: parentFiles) {
+                for (TWidget widget: childFile.getChildren()) {
                     TDirectoryTreeItem child = (TDirectoryTreeItem) widget;
                     if (child.getText().equals(p)) {
-                        childPath = child;
-                        childPath.setExpanded(true);
-                        childPath.onExpand();
+                        childFile = child;
+                        childFile.setExpanded(true);
+                        childFile.onExpand();
                         break;
                     }
                 }
             }
             unselect();
-            getTreeView().setSelected(childPath);
+            getTreeView().setSelected(childFile);
             setExpanded(oldExpanded);
         }
         getTreeView().reflow();
index 8055a3893563c7c248e10294de546820c6b4b9a3..9a3d16b5832e12514973c2a1bed795d9ef86ebff 100644 (file)
@@ -55,6 +55,17 @@ public class TField extends TWidget {
         return text;
     }
 
+    /**
+     * Set field text.
+     *
+     * @param text the new field text
+     */
+    public final void setText(String text) {
+        this.text = text;
+        position = 0;
+        windowStart = 0;
+    }
+
     /**
      * If true, only allow enough characters that will fit in the width.  If
      * false, allow the field to scroll to the right.
index eb2c924acee7aa507c7f1fe6043525894704c8bf..44d1538bc310cae4c9f8255a97d721dd6ea4a450 100644 (file)
@@ -90,7 +90,6 @@ public final class TFileOpenBox extends TWindow {
     /**
      * The right-side directory list pane.
      */
-    @SuppressWarnings("unused")
     private TDirectoryList directoryList;
 
     /**
@@ -104,36 +103,27 @@ public final class TFileOpenBox extends TWindow {
     private TButton openButton;
 
     /**
-     * Update the fields in response to other field updates.
+     * See if there is a valid filename to return.  If the filename is a
+     * directory, then
      *
-     * @param enter if true, the user manually entered a filename
+     * @param newFilename the filename to check and return
      */
-    @SuppressWarnings("unused")
-    private void onUpdate(boolean enter) throws IOException {
-        String newFilename = entryField.getText();
+    private void checkFilename(final String newFilename) throws IOException {
         File newFile = new File(newFilename);
         if (newFile.exists()) {
-            if (enter) {
-                if (newFile.isFile()) {
-                    filename = entryField.getText();
-                    getApplication().closeWindow(this);
-                }
-                if (newFile.isDirectory()) {
-                    treeViewRoot = new TDirectoryTreeItem(treeView,
-                        entryField.getText(), true);
-                    treeView.setTreeRoot(treeViewRoot, true);
-                    treeView.reflow();
-                }
+            if (newFile.isFile()) {
+                filename = newFilename;
+                getApplication().closeWindow(this);
+                return;
+            }
+            if (newFile.isDirectory()) {
+                treeViewRoot = new TDirectoryTreeItem(treeView, newFilename,
+                    true);
+                treeView.setTreeRoot(treeViewRoot, true);
+                treeView.reflow();
                 openButton.setEnabled(false);
-            } else {
-                if (newFile.isFile()) {
-                    openButton.setEnabled(true);
-                } else {
-                    openButton.setEnabled(false);
-                }
+                directoryList.setPath(newFilename);
             }
-        } else {
-            openButton.setEnabled(false);
         }
     }
 
@@ -154,13 +144,30 @@ public final class TFileOpenBox extends TWindow {
         entryField = addField(1, 1, getWidth() - 4, false,
             (new File(path)).getCanonicalPath(),
             new TAction() {
-                public void DO() {}
+                public void DO() {
+                    try {
+                        checkFilename(entryField.getText());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
             }, null);
+        entryField.onKeypress(new TKeypressEvent(kbEnd));
 
         // Add directory treeView
         treeView = addTreeView(1, 3, 30, getHeight() - 6,
             new TAction() {
-                public void DO() {}
+                public void DO() {
+                    TTreeItem item = treeView.getSelected();
+                    File selectedDir = ((TDirectoryTreeItem) item).getFile();
+                    try {
+                        directoryList.setPath(selectedDir.getCanonicalPath());
+                        openButton.setEnabled(false);
+                        activate(directoryList);
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
             }
         );
         treeViewRoot = new TDirectoryTreeItem(treeView, path, true);
@@ -168,7 +175,17 @@ public final class TFileOpenBox extends TWindow {
         // Add directory files list
         directoryList = addDirectoryList(path, 34, 3, 28, getHeight() - 6,
             new TAction() {
-                public void DO() {}
+                public void DO() {
+                    try {
+                        File newPath = directoryList.getPath();
+                        entryField.setText(newPath.getCanonicalPath());
+                        entryField.onKeypress(new TKeypressEvent(kbEnd));
+                        openButton.setEnabled(true);
+                        activate(entryField);
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
             }
         );
 
@@ -189,7 +206,13 @@ public final class TFileOpenBox extends TWindow {
         // Setup button actions
         openButton = addButton(openLabel, this.getWidth() - 12, 3,
             new TAction() {
-                public void DO() {}
+                public void DO() {
+                    try {
+                        checkFilename(entryField.getText());
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
             }
         );
         openButton.setEnabled(false);
@@ -203,6 +226,9 @@ public final class TFileOpenBox extends TWindow {
             }
         );
 
+        // Default to the directory list
+        activate(directoryList);
+
         // Set the secondaryFiber to run me
         getApplication().enableSecondaryEventReceiver(this);
 
index 11a81a7f8c1af6fc014e07d9d292fe96add861d7..9fb9330187018045489a8b4eaaad803a07a2f16b 100644 (file)
@@ -76,7 +76,7 @@ public class TTreeItem extends TWidget {
     /**
      * Set the displayable text for this item.
      *
-     * @param the displayable text for this item
+     * @param text the displayable text for this item
      */
     public final void setText(final String text) {
         this.text = text;
@@ -265,10 +265,10 @@ public class TTreeItem extends TWidget {
     /**
      * Recursively expand the tree into a linear array of items.
      *
-     * @param prefix vertical bar of parent levels and such that is set on
+     * @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
+     * @param last if true, this is the "last" leaf node of a tree
+     * @return additional items to add to the array
      */
     public List<TTreeItem> expandTree(final String prefix, final boolean last) {
         List<TTreeItem> array = new ArrayList<TTreeItem>();
index a6855ba83c44088bda82fc68737c5742d4d8bbfc..c24fd0cba0cebc945a1c672abc9e8d2e5a1f2f16 100644 (file)
@@ -435,12 +435,20 @@ public class TTreeView extends TWidget {
                     }
                 }
             }
+        } 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 to TWidget's handler.
             super.onKeypress(keypress);
+            return;
         }
 
         // Update the screen after any thing has expanded/contracted
index 29b6c72217e546abe52fb58749e97dd1b89a9d0d..91bcfced72e81128b581c6049975485fd0446f77 100644 (file)
@@ -762,8 +762,7 @@ public abstract class TWidget implements Comparable<TWidget> {
     public void onKeypress(final TKeypressEvent keypress) {
 
         if ((children.size() == 0)
-            // TODO
-            // || (cast(TTreeView)this)
+            || (this instanceof TTreeView)
             || (this instanceof TText)
         ) {
 
index 95d0a54f81d4c8e1fe9b781fcf02a07e81f32e51..d9bbeb765db92d45aca5537fe274f9b288c42c92 100644 (file)
 package jexer.demos;
 
 import java.io.*;
+import java.util.*;
 
 import jexer.*;
+import jexer.event.*;
 import jexer.menu.*;
 
 /**
@@ -74,7 +76,7 @@ public class DemoApplication extends TApplication {
 
         addWindowMenu();
     }
-    
+
     /**
      * Public constructor.
      *
@@ -93,7 +95,47 @@ public class DemoApplication extends TApplication {
         super(input, output);
         addAllWidgets();
     }
-    
+
+    /**
+     * Handle menu events.
+     *
+     * @param menu menu event
+     * @return if true, the event was processed and should not be passed onto
+     * a window
+     */
+    @Override
+    public boolean onMenu(TMenuEvent menu) {
+        if (menu.getId() == TMenu.MID_OPEN_FILE) {
+            try {
+                String filename = fileOpenBox(".");
+                 if (filename != null) {
+                     try {
+                         File file = new File(filename);
+                         StringBuilder fileContents = new StringBuilder();
+                         Scanner scanner = new Scanner(file);
+                         String EOL = System.getProperty("line.separator");
+
+                         try {
+                             while(scanner.hasNextLine()) {
+                                 fileContents.append(scanner.nextLine() + EOL);
+                             }
+                             new DemoTextWindow(this, filename,
+                                 fileContents.toString());
+                         } finally {
+                             scanner.close();
+                         }
+                     } catch (IOException e) {
+                         e.printStackTrace();
+                     }
+                 }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            return true;
+        }
+        return super.onMenu(menu);
+    }
+
     /**
      * Public constructor.
      *
index 711bf3bf9ff6dab2795f246339d9ee784a4e88e7..265c45db7f6f73ae1d8666f78d1772a2b519b6b5 100644 (file)
@@ -43,15 +43,27 @@ public class DemoTextWindow extends TWindow {
      */
     private TText textField;
 
+    /**
+     * Public constructor makes a text window out of any string.
+     *
+     * @param parent the main application
+     * @param title the text string
+     * @param text the text string
+     */
+    public DemoTextWindow(final TApplication parent, final String title,
+        final String text) {
+
+        super(parent, title, 0, 0, 44, 20, RESIZABLE);
+        textField = addText(text, 1, 1, 40, 16);
+    }
+    
     /**
      * Public constructor.
      *
      * @param parent the main application
      */
     public DemoTextWindow(final TApplication parent) {
-        super(parent, "Text Areas", 0, 0, 44, 20, RESIZABLE);
-
-        textField = addText(
+        this(parent, "Text Area",
 "This is an example of a reflowable text field.  Some example text follows.\n" +
 "\n" +
 "This library implements a text-based windowing system loosely\n" +
@@ -69,8 +81,8 @@ public class DemoTextWindow extends TWindow {
 "This library is licensed LGPL (\"GNU Lesser General Public License\")\n" +
 "version 3 or greater.  See the file COPYING for the full license text,\n" +
 "which includes both the GPL v3 and the LGPL supplemental terms.\n" +
-"\n",
-            1, 1, 40, 16);
+"\n");
+
     }
 
     /**