Package org.jnode.apps.commander

Source Code of org.jnode.apps.commander.CharvaCommander

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library 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 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.apps.commander;

import charva.awt.BorderLayout;
import charva.awt.Color;
import charva.awt.EventQueue;
import charva.awt.Insets;
import charva.awt.Point;
import charva.awt.Toolkit;
import charva.awt.event.ActionEvent;
import charva.awt.event.ActionListener;
import charva.awt.event.KeyEvent;
import charva.awt.event.ScrollEvent;
import charvax.swing.JButton;
import charvax.swing.JFrame;
import charvax.swing.JLabel;
import charvax.swing.JList;
import charvax.swing.JOptionPane;
import charvax.swing.JPanel;
import charvax.swing.JScrollPane;
import charvax.swing.border.TitledBorder;
import charvax.swing.event.ListSelectionEvent;
import charvax.swing.event.ListSelectionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
* Charva based file manager.
*
* @author Levente S\u00e1ntha
*/
public class CharvaCommander extends JFrame {
    private static final Color BACKGROUND_COLOR = Color.black;
    private static final Color FOREGROUND_COLOR = Color.cyan;
    private static final Color HIGHLIGHT_COLOR = Color.yellow;
    private Pane leftPane;
    private Pane rightPane;
    private boolean exitted;

    /**
     * Startup method.
     *
     * @param argv ignored
     */
    public static void main(String[] argv) {
        CharvaCommander cmd = null;
        try {
            Toolkit.getDefaultToolkit().register();
            cmd = new CharvaCommander();
            cmd.setVisible(true);
            //Toolkit.getDefaultToolkit().waitTillFinished();
        } catch (Exception e) {
            e.printStackTrace();
            if (cmd != null)
                cmd.exit();
            else
                Toolkit.getDefaultToolkit().close();
        }
    }

    private CharvaCommander() {
        this._insets = new Insets(0, 0, 0, 0);
        setBackground(BACKGROUND_COLOR);
        setForeground(FOREGROUND_COLOR);
        JPanel content = (JPanel) getContentPane();
        new ButtonPanel();

        JPanel panel = new JPanel();
        content.add(panel, BorderLayout.CENTER);
        panel.setLayout(null);

        File startf = new File(".");
        String path = startf.getAbsolutePath();
        try {
            path = startf.getCanonicalPath();
        } catch (IOException e) {
            //ignore
        }

        leftPane = new Pane(38, 20);
        leftPane.setPath(path);
        leftPane.setLocation(0, 0);
        panel.add(leftPane);
        leftPane.label.setLocation(1, 22);
        panel.add(leftPane.label);

        rightPane = new Pane(38, 20);
        rightPane.setPath(path);
        rightPane.setLocation(40, 0);
        panel.add(rightPane);
        rightPane.label.setLocation(41, 22);
        panel.add(rightPane.label);

        setLocation(0, 0);
        setSize(80, 24);
        validate();

        leftPane.list.requestFocus();
        leftPane.border.setTitleColor(HIGHLIGHT_COLOR);
    }

    private class ButtonPanel extends JPanel implements ActionListener {
        {
            getContentPane().add(this, BorderLayout.SOUTH);
        }

        //final JButton help = createButton("1 Help", KeyEvent.VK_F1);
        final JButton mkfile = createButton("F2 New", KeyEvent.VK_F2);
        final JButton view = createButton("F3 View", KeyEvent.VK_F3);
        final JButton edit = createButton("F4 Edit", KeyEvent.VK_F4);
        final JButton copy = createButton("F5 Copy", KeyEvent.VK_F5);
        final JButton move = createButton("F6 Move", KeyEvent.VK_F6);
        final JButton mkdir = createButton("F7 MkDir", KeyEvent.VK_F7);
        final JButton delte = createButton("F8 Delete", KeyEvent.VK_F8);
        final JButton chdir = createButton("F9 ChDir", KeyEvent.VK_F9);
        final JButton exit = createButton("F10 Exit", KeyEvent.VK_F10);

        JButton createButton(String title, int accel) {
            JButton b = new MyButton(title);
            this.add(b);
            b.setMnemonic(accel);
            b.addActionListener(this);
            return b;
        }

        public void actionPerformed(ActionEvent ae) {
            try {
                Object source = ae.getSource();
                //if (source == help) {
                //} else
                if (source == mkfile) {
                    mkfile();
                } else if (source == view) {
                    view();
                } else if (source == edit) {
                    edit();
                } else if (source == copy) {
                    copy();
                } else if (source == move) {
                    move();
                } else if (source == mkdir) {
                    mkdir();
                } else if (source == delte) {
                    delete();
                } else if (source == chdir) {
                    chdir();
                } else if (source == exit) {
                    exit();
                }
            } finally {
                if (!exitted)
                    leftPane.requestFocus();
            }
        }
    }

    private synchronized void move() {
        String sel = leftPane.getSelection();
        if (sel == null)
            return;

        int conf = JOptionPane
            .showConfirmDialog(this, sel + " to " + rightPane.getPath(), "Move ?", JOptionPane.YES_NO_OPTION);
        if (conf != JOptionPane.YES_OPTION)
            return;

        int index = leftPane.list.getSelectedIndex();
        try {
            File source = new File(leftPane.getPath(), sel);
            if (copyRec(source, new File(rightPane.getPath(), sel), true))
                delete0(source);
        } finally {
            leftPane.setPath(leftPane.getPath());
            leftPane.list.setCurrentRow(index);
            leftPane.repaint();
            rightPane.setPath(rightPane.getPath(), sel);
            rightPane.repaint();
        }
    }

    private synchronized void view() {
        String sel = leftPane.getSelection();
        if (sel == null)
            return;

        File f = new File(leftPane.getPath(), sel);
        if (!f.isFile())
            return;

        callViewer(f);
    }

    private synchronized void mkfile() {
        String str = JOptionPane.showInputDialog(this, "File name: ", "New file", JOptionPane.OK_CANCEL_OPTION);
        if (str == null || str.trim().length() == 0)
            return;

        File file = new File(leftPane.getPath(), str);
        if (file.exists()) {
            int conf = JOptionPane
                .showConfirmDialog(this, file.getName(), "Continue? File already exits:", JOptionPane.YES_NO_OPTION);
            if (conf != JOptionPane.YES_OPTION)
                return;
        } else {
            try {
                file.createNewFile();
            } catch (IOException ioe) {
                JOptionPane.showMessageDialog(this, "Could not create file: " + file.getName());
                return;
            }
        }

        callEditor(file);
        leftPane.setPath(leftPane.getPath(), file.getName());
        leftPane.repaint();
    }

    private void callViewer(File file) {
        try {
            Class.forName("org.jnode.apps.editor.TextEditor").getMethod("main", String[].class).
                invoke(null, new Object[]{new String[]{file.getAbsolutePath(), "ro"}});
        } catch (ClassNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Viewer not found", "Warning", JOptionPane.DEFAULT_OPTION);
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.DEFAULT_OPTION);
        }

    }

    private synchronized void edit() {
        String sel = leftPane.getSelection();
        if (sel == null)
            return;

        File f = new File(leftPane.getPath(), sel);
        if (!f.isFile())
            return;

        callEditor(f);
    }

    private void callEditor(File file) {
        try {
            Class.forName("org.jnode.apps.editor.TextEditor").getMethod("main", String[].class).
                invoke(null, new Object[]{new String[]{file.getAbsolutePath()}});
        } catch (ClassNotFoundException e) {
            JOptionPane.showMessageDialog(this, "Editor not found", "Warning", JOptionPane.DEFAULT_OPTION);
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.DEFAULT_OPTION);
        }
    }

    private synchronized void chdir() {
        String str =
            JOptionPane.showInputDialog(this, "Path to directory: ", "Change directory", JOptionPane.OK_CANCEL_OPTION);
        if (str == null || str.trim().length() == 0)
            return;

        File f = str.charAt(0) == '/' ? new File(str) :
            new File(leftPane.getPath(), str);

        if (!f.exists())
            JOptionPane.showMessageDialog(this, f.getAbsolutePath(), "Invalid directory", JOptionPane.DEFAULT_OPTION);
        else {
            if (!f.isDirectory())
                f = f.getParentFile();

            leftPane.setPath(f.getAbsolutePath());
            leftPane.repaint();
        }
    }

    private synchronized void delete() {
        String sel = leftPane.getSelection();
        if (sel == null)
            return;

        int conf = JOptionPane.showConfirmDialog(this, sel, "Delete ?", JOptionPane.YES_NO_OPTION);
        if (conf != JOptionPane.YES_OPTION)
            return;

        File f = new File(leftPane.getPath(), sel);
        if (f.isDirectory() && f.list().length > 0) {
            conf = JOptionPane
                .showConfirmDialog(this, "Directory is not empty: " + sel, "Delete ?", JOptionPane.YES_NO_OPTION);
            if (conf != JOptionPane.YES_OPTION)
                return;
        }

        int index = leftPane.list.getSelectedIndex();
        try {
            delete0(new File(leftPane.getPath(), sel));
        } finally {
            leftPane.setPath(leftPane.getPath());
            leftPane.list.setCurrentRow(index);
            leftPane.repaint();
        }
    }

    private void delete0(File f) {
        if (f.isDirectory())
            for (String s : f.list())
                delete0(new File(f.getAbsolutePath(), s));

        f.delete();
    }

    @SuppressWarnings("unused")
    private void notImplemented() {
        JOptionPane.showMessageDialog(this, "NOT IMPLEMENTED!", null, JOptionPane.DEFAULT_OPTION);
        leftPane.requestFocus();
    }

    private synchronized void copy() {
        String sel = leftPane.getSelection();
        if (sel == null)
            return;

        int conf = JOptionPane
            .showConfirmDialog(this, sel + " to " + rightPane.getPath(), "Copy ?", JOptionPane.YES_NO_OPTION);
        if (conf != JOptionPane.YES_OPTION)
            return;

        try {
            copyRec(new File(leftPane.getPath(), sel), new File(rightPane.getPath(), sel), true);
        } finally {
            rightPane.setPath(rightPane.getPath(), sel);
            rightPane.repaint();
        }
    }

    private boolean copyRec(File from, File to, boolean ask) {
        if (from.isFile()) {
            return copy0(from, to, ask);
        } else if (from.isDirectory()) {
            if (ask && to.exists()) {
                int conf = JOptionPane.showConfirmDialog(this, to.toString(), "Overwrite ?", JOptionPane.YES_NO_OPTION);
                if (conf != JOptionPane.YES_OPTION)
                    return false;
            } else
                to.mkdir();

            for (String name : from.list())
                if (!copyRec(new File(from.getAbsolutePath(), name), new File(to.getAbsolutePath(), name), false))
                    return false;

            return true;
        } else {
            JOptionPane.showMessageDialog(this, "Unsupported file type in source.");
            return false;
        }
    }

    private boolean copy0(File from, File to, boolean ask) {
        if (from.equals(to)) {
            JOptionPane.showMessageDialog(this, "Source and destination files are the same.");
            return false;
        }
        if (ask && to.exists()) {
            int conf = JOptionPane.showConfirmDialog(this, to.toString(), "Overwrite ?", JOptionPane.YES_NO_OPTION);
            if (conf != JOptionPane.YES_OPTION)
                return false;
        }
        try {
            copy0(new FileInputStream(from), new FileOutputStream(to));
            return true;
        } catch (IOException e) {
            JOptionPane.showMessageDialog(this, e.getMessage(), "Error", JOptionPane.OK_OPTION);
            to.delete();
            return false;
        }
    }

    private void copy0(FileInputStream in, FileOutputStream out) throws IOException {
        try {
            byte[] buf = new byte[8 * 1024];
            int c;
            while ((c = in.read(buf)) > -1)
                out.write(buf, 0, c);
            out.flush();
        } finally {
            in.close();
            out.close();
        }
    }

    private synchronized void mkdir() {
        String str = JOptionPane.showInputDialog(this, "Directory name: ", "Create directory",
            JOptionPane.OK_CANCEL_OPTION);
        if (str != null && str.trim().length() > 0) {
            File file = new File(leftPane.getPath(), str);
            file.mkdir();
            leftPane.setPath(leftPane.getPath(), "/" + file.getName());
            leftPane.repaint();
        }
    }

    private synchronized void exit() {
        exitted = true;
        hide();
        Toolkit.getDefaultToolkit().close();
    }

    private static void format(String str, int limit, StringBuilder sb) {
        if (str.length() > limit) {
            int half = limit / 2;
            if (2 * half < limit) {
                str = str.substring(0, half) + '~' + str.substring(str.length() - half);
            } else {
                str = str.substring(0, half) + '~' + str.substring(str.length() - half + 1);
            }
        }
        sb.append(str);
        int ln = str.length();
        while (ln++ < limit) {
            sb.append(' ');
        }
    }

    private static class ListDataEntry implements Comparable {
        final File file;
        final String name;
        private final String text;

        ListDataEntry(File file, String text) {
            this.file = file;
            this.name = text;
            this.text = text;
        }

        ListDataEntry(File file) {
            SimpleDateFormat df = new SimpleDateFormat("dd/MM/yy HH:mm");
            char vline = (char) Toolkit.ACS_VLINE;
            this.file = file;
            this.name = (file.isDirectory() ? "/" : "") + file.getName();
            StringBuilder text = new StringBuilder();
            text.append((file.isDirectory() ? '/' : ' '));
            CharvaCommander.format(file.getName(), 15, text);
            text.append(vline);
            format(file.length(), text);
            text.append(vline);
            text.append(df.format(new Date(file.lastModified())));
            this.text = text.toString();
        }

        private static final char[] UNITS = {'B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'};

        private void format(long size, StringBuilder sb) {
            String s = String.valueOf(size);
            int index = 0;
            while (s.length() > 5) {
                size /= 1024;
                s = String.valueOf(size);
                index++;
            }
            int ln = s.length();
            while (ln++ < 5) {
                sb.append(' ');
            }
            sb.append(s);
            sb.append(UNITS[index]);
        }

        public String toString() {
            return text;
        }

        @Override
        public int compareTo(Object o) {
            ListDataEntry other = (ListDataEntry) o;
            boolean thisDirectory = this.file.isDirectory();
            if (!(thisDirectory ^ other.file.isDirectory())) {
                return name.compareTo(other.name);
            } else {
                return thisDirectory ? -1 : 1;
            }
        }
    }

    private class Pane extends JScrollPane implements ListSelectionListener {
        String path;
        MyList list;
        TitledBorder border;
        JLabel label = new JLabel();
        int w;
        int h;

        Pane(int w, int h) {
            this.w = w;
            this.h = h;
            border = new TitledBorder("");
            border.setTitleColor(FOREGROUND_COLOR);
            list = new MyList();
            setViewportView(list);
            list.setVisibleRowCount(h);
            list.setColumns(w);
            list.addListSelectionListener(this);
            this.setViewportBorder(border);
            this.setForeground(FOREGROUND_COLOR);
        }

        private void handleFocus() {
            if (leftPane != this) {
                rightPane = leftPane;
                leftPane = this;
                leftPane.border.setTitleColor(HIGHLIGHT_COLOR);
                rightPane.border.setTitleColor(FOREGROUND_COLOR);
                rightPane.repaint();
            }
        }

        private int setData(String s, String n) {
            File file = new File(s);
            if (file.isDirectory()) {
                setPath0(s);
                File[] files = file.listFiles();
                ListDataEntry[] names = new ListDataEntry[files == null ? 0 : files.length];

                //prefix dirs with '/'
                int i = 0;
                if (files != null) {
                    for (File f : files)
                        names[i++] = new ListDataEntry(f);
                }

                Arrays.sort(names);
                //add parent entry: ".."
                if (!"/".equals(s)) {
                    int ln = names.length;
                    ListDataEntry[] names2 = new ListDataEntry[ln + 1];
                    names2[0] = new ListDataEntry(file, "..");
                    System.arraycopy(names, 0, names2, 1, ln);
                    names = names2;
                }

                list.setListData(names);

                //set list selection
                if (n == null) {
                    list.setSelectedIndex(0);
                    return 0;
                } else {
                    i = 0;
                    for (ListDataEntry nn : names) {
                        if (n.equals(nn.name)) {
                            return i;
                        }
                        i++;
                    }

                    return 0;
                }
            }
            return -1;
        }

        public String getPath() {
            return path;
        }

        public void setPath(String path) {
            setPath0(path);
            setData(path, null);
        }

        public void setPath(String path, String selection) {
            setPath0(path);
            int index = setData(path, selection);
            list.setCurrentRow(index);
        }

        public String getSelection() {
            String sel = ((ListDataEntry) list.getSelectedValue()).name;
            if (sel == null || sel.equals(".."))
                return null;

            if (sel.charAt(0) == '/')
                return sel.substring(1);

            return sel;
        }

        private void setPath0(String path) {
            this.path = path;
            setBorder(path);
        }

        private void setBorder(String path) {
            int w = this.w - 2;
            if (w > 0 && path.length() > w) {
                path = path.substring(path.length() - w);
            }
            border.setTitle(path);
        }

        @Override
        public void valueChanged(ListSelectionEvent evt) {
            if (label != null) {
                if (list.getModel().getSize() > evt.getFirstIndex()) {
                    String selection = getSelection();
                    if (selection == null) {
                        label.setText("");
                    } else {
                        StringBuilder sb = new StringBuilder();
                        format(selection, 38, sb);
                        label.setText(sb.toString());
                    }
                }
            }
        }

        private class MyList extends JList {
            @Override
            public void processKeyEvent(KeyEvent ke) {
                EventQueue evtqueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
                int keyCode = ke.getKeyCode();
                if (keyCode == KeyEvent.VK_ENTER) {
                    Object sel = ((ListDataEntry) list.getSelectedValue()).name;
                    String s;
                    String n = null;
                    if ("..".equals(sel)) {
                        File file = new File(path);
                        n = file.getName();
                        s = file.getParentFile().getAbsolutePath();
                    } else {
                        String sels = String.valueOf(sel);
                        s = new File(path, sels.substring(1, sels.length())).getAbsolutePath();
                    }
                    int sri = setData(s, "/" + n);
                    int dir = _currentRow < sri ? ScrollEvent.UP : ScrollEvent.DOWN;
                    if (sri > -1)
                        _currentRow = sri;
                    setSelectedIndex(_currentRow);
                    evtqueue.postEvent(new ScrollEvent(this, dir, new Point(0, _currentRow)));
                    ke.consume();
                } else if (keyCode == KeyEvent.VK_HOME) {
                    _currentRow = 0;
                    evtqueue.postEvent(new ScrollEvent(
                        this, ScrollEvent.DOWN, new Point(0, _currentRow)));
                }
                super.processKeyEvent(ke);
                if (keyCode == KeyEvent.VK_UP ||
                    keyCode == KeyEvent.VK_DOWN ||
                    keyCode == KeyEvent.VK_PAGE_UP ||
                    keyCode == KeyEvent.VK_PAGE_DOWN ||
                    keyCode == KeyEvent.VK_END ||
                    keyCode == KeyEvent.VK_HOME) {
                    setSelectedIndex(_currentRow);
                }
            }

            @Override
            public void requestFocus() {
                super.requestFocus();
                handleFocus();
            }

            void setCurrentRow(int index) {
                if (index > -1) {
                    int size = list.getModel().getSize();
                    if (index >= size) {
                        index = size - 1;
                    }
                    int dir = _currentRow < index ? ScrollEvent.UP : ScrollEvent.DOWN;
                    _currentRow = index;
                    setSelectedIndex(_currentRow);
                    Toolkit.getDefaultToolkit().getSystemEventQueue().
                        postEvent(new ScrollEvent(this, dir, new Point(0, _currentRow)));
                }
            }
        }
    }

    private static class MyButton extends JButton {
        public MyButton() {
            this("");
        }

        public MyButton(String text_) {
            super(text_);
        }

        @Override
        public boolean isFocusTraversable() {
            return false;
        }


        @Override
        protected String getLabelString() {
            return getText();
        }

        public int getWidth() {
            return getLabelString().length();
        }

        @Override
        public void draw(Toolkit toolkit) {
            Point origin = getLocationOnScreen();
            toolkit.setCursor(origin);
            int colorpair = getCursesColor();
            toolkit.addString(getLabelString(), Toolkit.A_REVERSE, colorpair);
        }
    }
}
TOP

Related Classes of org.jnode.apps.commander.CharvaCommander

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.