Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

644
LINES

< > BotCompany Repo | #1006655 // FileBro [works, but interface has little quirks]

JavaX source code [tags: use-pretranspiled] - run with: x30.jar

Libraryless. Click here for Pure Java version (3175L/22K/74K).

1  
!7
2  
3  
import javax.swing.*;
4  
import javax.swing.border.*;
5  
import javax.swing.event.*;
6  
import javax.swing.tree.*;
7  
import javax.swing.table.*;
8  
import javax.swing.filechooser.FileSystemView;
9  
10  
import javax.imageio.ImageIO;
11  
12  
import java.util.Date;
13  
import java.util.List;
14  
import java.util.ArrayList;
15  
16  
import java.io.*;
17  
import java.nio.channels.FileChannel;
18  
19  
import java.net.URL;
20  
21  
/**
22  
A basic File Browser.  Requires 1.6+ for the Desktop & SwingWorker
23  
classes, amongst other minor things.
24  
25  
Includes support classes FileTableModel & FileTreeCellRenderer.
26  
27  
@TODO Bugs
28  
<li>Fix keyboard focus issues - especially when functions like
29  
rename/delete etc. are called that update nodes & file lists.
30  
<li>Needs more testing in general.
31  
32  
@TODO Functionality
33  
<li>Double clicking a directory in the table, should update the tree
34  
<li>Move progress bar?
35  
<li>Add other file display modes (besides table) in CardLayout?
36  
<li>Menus + other cruft?
37  
<li>Implement history/back
38  
<li>Allow multiple selection
39  
<li>Add file search
40  
41  
@author Andrew Thompson
42  
@version 2011-06-08
43  
@see http://codereview.stackexchange.com/q/4446/7784
44  
@license LGPL
45  
*/
46  
47  
p-substance {
48  
  FileBrowser.main(args);
49  
}
50  
51  
sclass FileBrowser {
52  
53  
    /** Title of the application */
54  
    public static final String APP_TITLE = "FileBro";
55  
    /** Used to open/edit/print files. */
56  
    private Desktop desktop;
57  
    /** Provides nice icons and names for files. */
58  
    private FileSystemView fileSystemView;
59  
60  
    /** currently selected File. */
61  
    private File currentFile;
62  
63  
    /** Main GUI container */
64  
    private JPanel gui;
65  
66  
    /** File-system tree. Built Lazily */
67  
    private JTree tree;
68  
    private DefaultTreeModel treeModel;
69  
70  
    /** Directory listing */
71  
    private JTable table;
72  
    private JProgressBar progressBar;
73  
    /** Table model for File[]. */
74  
    private FileTableModel fileTableModel;
75  
    private ListSelectionListener listSelectionListener;
76  
    private boolean cellSizesSet = false;
77  
    private int rowIconPadding = 6;
78  
79  
    /* File controls. */
80  
    private JButton openFile;
81  
    private JButton printFile;
82  
    private JButton editFile;
83  
84  
    /* File details. */
85  
    private JLabel fileName;
86  
    private JTextField path;
87  
    private JLabel date;
88  
    private JLabel size;
89  
    private JCheckBox readable;
90  
    private JCheckBox writable;
91  
    private JCheckBox executable;
92  
    private JRadioButton isDirectory;
93  
    private JRadioButton isFile;
94  
95  
    /* GUI options/containers for new File/Directory creation.  Created lazily. */
96  
    private JPanel newFilePanel;
97  
    private JRadioButton newTypeFile;
98  
    private JTextField name;
99  
100  
    public Container getGui() {
101  
        if (gui==null) {
102  
            gui = new JPanel(new BorderLayout(3,3));
103  
            gui.setBorder(new EmptyBorder(5,5,5,5));
104  
105  
            fileSystemView = FileSystemView.getFileSystemView();
106  
            desktop = Desktop.getDesktop();
107  
108  
            JPanel detailView = new JPanel(new BorderLayout(3,3));
109  
110  
            table = new JTable();
111  
            table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
112  
            table.setAutoCreateRowSorter(true);
113  
            table.setShowVerticalLines(false);
114  
115  
            listSelectionListener = new ListSelectionListener() {
116  
                @Override
117  
                public void valueChanged(ListSelectionEvent lse) {
118  
                    int row = table.getSelectionModel().getLeadSelectionIndex();
119  
                    setFileDetails( ((FileTableModel)table.getModel()).getFile(row) );
120  
                }
121  
            };
122  
            table.getSelectionModel().addListSelectionListener(listSelectionListener);
123  
            JScrollPane tableScroll = new JScrollPane(table);
124  
            Dimension d = tableScroll.getPreferredSize();
125  
            tableScroll.setPreferredSize(new Dimension((int)d.getWidth(), (int)d.getHeight()/2));
126  
            detailView.add(tableScroll, BorderLayout.CENTER);
127  
128  
            // the File tree
129  
            DefaultMutableTreeNode root = new DefaultMutableTreeNode();
130  
            treeModel = new DefaultTreeModel(root);
131  
132  
            TreeSelectionListener treeSelectionListener = new TreeSelectionListener() {
133  
                public void valueChanged(TreeSelectionEvent tse){
134  
                    DefaultMutableTreeNode node =
135  
                        (DefaultMutableTreeNode)tse.getPath().getLastPathComponent();
136  
                    showChildren(node);
137  
                    setFileDetails((File)node.getUserObject());
138  
                }
139  
            };
140  
141  
            // show the file system roots.
142  
            File[] roots = fileSystemView.getRoots();
143  
            for (File fileSystemRoot : roots) {
144  
                DefaultMutableTreeNode node = new DefaultMutableTreeNode(fileSystemRoot);
145  
                root.add( node );
146  
                File[] files = fileSystemView.getFiles(fileSystemRoot, true);
147  
                for (File file : files) {
148  
                    if (file.isDirectory()) {
149  
                        node.add(new DefaultMutableTreeNode(file));
150  
                    }
151  
                }
152  
                //
153  
            }
154  
155  
            tree = new JTree(treeModel);
156  
            tree.setRootVisible(false);
157  
            tree.addTreeSelectionListener(treeSelectionListener);
158  
            tree.setCellRenderer(new FileTreeCellRenderer());
159  
            tree.expandRow(0);
160  
            JScrollPane treeScroll = new JScrollPane(tree);
161  
162  
            // as per trashgod tip
163  
            tree.setVisibleRowCount(15);
164  
165  
            Dimension preferredSize = treeScroll.getPreferredSize();
166  
            Dimension widePreferred = new Dimension(
167  
                200,
168  
                (int)preferredSize.getHeight());
169  
            treeScroll.setPreferredSize( widePreferred );
170  
171  
            // details for a File
172  
            JPanel fileMainDetails = new JPanel(new BorderLayout(4,2));
173  
            fileMainDetails.setBorder(new EmptyBorder(0,6,0,6));
174  
175  
            JPanel fileDetailsLabels = new JPanel(new GridLayout(0,1,2,2));
176  
            fileMainDetails.add(fileDetailsLabels, BorderLayout.WEST);
177  
178  
            JPanel fileDetailsValues = new JPanel(new GridLayout(0,1,2,2));
179  
            fileMainDetails.add(fileDetailsValues, BorderLayout.CENTER);
180  
181  
            fileDetailsLabels.add(new JLabel("File", JLabel.TRAILING));
182  
            fileName = new JLabel();
183  
            fileDetailsValues.add(fileName);
184  
            fileDetailsLabels.add(new JLabel("Path/name", JLabel.TRAILING));
185  
            path = new JTextField(5);
186  
            path.setEditable(false);
187  
            fileDetailsValues.add(path);
188  
            fileDetailsLabels.add(new JLabel("Last Modified", JLabel.TRAILING));
189  
            date = new JLabel();
190  
            fileDetailsValues.add(date);
191  
            fileDetailsLabels.add(new JLabel("File size", JLabel.TRAILING));
192  
            size = new JLabel();
193  
            fileDetailsValues.add(size);
194  
            fileDetailsLabels.add(new JLabel("Type", JLabel.TRAILING));
195  
196  
            JPanel flags = new JPanel(new FlowLayout(FlowLayout.LEADING,4,0));
197  
198  
            isDirectory = new JRadioButton("Directory");
199  
            flags.add(isDirectory);
200  
201  
            isFile = new JRadioButton("File");
202  
            flags.add(isFile);
203  
            fileDetailsValues.add(flags);
204  
205  
            JToolBar toolBar = new JToolBar();
206  
            // mnemonics stop working in a floated toolbar
207  
            toolBar.setFloatable(false);
208  
209  
            JButton locateFile = new JButton("Locate");
210  
            locateFile.setMnemonic('l');
211  
212  
            locateFile.addActionListener(new ActionListener(){
213  
                public void actionPerformed(ActionEvent ae) {
214  
                    try {
215  
                        System.out.println("Locate: " + currentFile.getParentFile());
216  
                        desktop.open(currentFile.getParentFile());
217  
                    } catch(Throwable t) {
218  
                        showThrowable(t);
219  
                    }
220  
                    gui.repaint();
221  
                }
222  
            });
223  
            toolBar.add(locateFile);
224  
225  
            openFile = new JButton("Open");
226  
            openFile.setMnemonic('o');
227  
228  
            openFile.addActionListener(new ActionListener(){
229  
                public void actionPerformed(ActionEvent ae) {
230  
                    try {
231  
                        System.out.println("Open: " + currentFile);
232  
                        desktop.open(currentFile);
233  
                    } catch(Throwable t) {
234  
                        showThrowable(t);
235  
                    }
236  
                    gui.repaint();
237  
                }
238  
            });
239  
            toolBar.add(openFile);
240  
241  
            editFile = new JButton("Edit");
242  
            editFile.setMnemonic('e');
243  
            editFile.addActionListener(new ActionListener(){
244  
                public void actionPerformed(ActionEvent ae) {
245  
                    try {
246  
                        desktop.edit(currentFile);
247  
                    } catch(Throwable t) {
248  
                        showThrowable(t);
249  
                    }
250  
                }
251  
            });
252  
            toolBar.add(editFile);
253  
254  
            printFile = new JButton("Print");
255  
            printFile.setMnemonic('p');
256  
            printFile.addActionListener(new ActionListener(){
257  
                public void actionPerformed(ActionEvent ae) {
258  
                    try {
259  
                        desktop.print(currentFile);
260  
                    } catch(Throwable t) {
261  
                        showThrowable(t);
262  
                    }
263  
                }
264  
            });
265  
            toolBar.add(printFile);
266  
267  
            // Check the actions are supported on this platform!
268  
            openFile.setEnabled(desktop.isSupported(Desktop.Action.OPEN));
269  
            editFile.setEnabled(desktop.isSupported(Desktop.Action.EDIT));
270  
            printFile.setEnabled(desktop.isSupported(Desktop.Action.PRINT));
271  
272  
            flags.add(new JLabel("::  Flags"));
273  
            readable = new JCheckBox("Read  ");
274  
            readable.setMnemonic('a');
275  
            flags.add(readable);
276  
277  
            writable = new JCheckBox("Write  ");
278  
            writable.setMnemonic('w');
279  
            flags.add(writable);
280  
281  
            executable = new JCheckBox("Execute");
282  
            executable.setMnemonic('x');
283  
            flags.add(executable);
284  
285  
            int count = fileDetailsLabels.getComponentCount();
286  
            for (int ii=0; ii<count; ii++) {
287  
                fileDetailsLabels.getComponent(ii).setEnabled(false);
288  
            }
289  
290  
            count = flags.getComponentCount();
291  
            for (int ii=0; ii<count; ii++) {
292  
                flags.getComponent(ii).setEnabled(false);
293  
            }
294  
295  
            JPanel fileView = new JPanel(new BorderLayout(3,3));
296  
297  
            fileView.add(toolBar,BorderLayout.NORTH);
298  
            fileView.add(fileMainDetails,BorderLayout.CENTER);
299  
300  
            detailView.add(fileView, BorderLayout.SOUTH);
301  
302  
            JSplitPane splitPane = new JSplitPane(
303  
                JSplitPane.HORIZONTAL_SPLIT,
304  
                treeScroll,
305  
                detailView);
306  
            gui.add(splitPane, BorderLayout.CENTER);
307  
308  
            JPanel simpleOutput = new JPanel(new BorderLayout(3,3));
309  
            progressBar = new JProgressBar();
310  
            simpleOutput.add(progressBar, BorderLayout.EAST);
311  
            progressBar.setVisible(false);
312  
313  
            gui.add(simpleOutput, BorderLayout.SOUTH);
314  
315  
        }
316  
        return gui;
317  
    }
318  
319  
    public void showRootFile() {
320  
        // ensure the main files are displayed
321  
        tree.setSelectionInterval(0,0);
322  
    }
323  
324  
    private TreePath findTreePath(File find) {
325  
        for (int ii=0; ii<tree.getRowCount(); ii++) {
326  
            TreePath treePath = tree.getPathForRow(ii);
327  
            Object object = treePath.getLastPathComponent();
328  
            DefaultMutableTreeNode node = (DefaultMutableTreeNode)object;
329  
            File nodeFile = (File)node.getUserObject();
330  
331  
            if (nodeFile==find) {
332  
                return treePath;
333  
            }
334  
        }
335  
        // not found!
336  
        return null;
337  
    }
338  
339  
    private void showErrorMessage(String errorMessage, String errorTitle) {
340  
        JOptionPane.showMessageDialog(
341  
            gui,
342  
            errorMessage,
343  
            errorTitle,
344  
            JOptionPane.ERROR_MESSAGE
345  
            );
346  
    }
347  
348  
    private void showThrowable(Throwable t) {
349  
        t.printStackTrace();
350  
        JOptionPane.showMessageDialog(
351  
            gui,
352  
            t.toString(),
353  
            t.getMessage(),
354  
            JOptionPane.ERROR_MESSAGE
355  
            );
356  
        gui.repaint();
357  
    }
358  
359  
    /** Update the table on the EDT */
360  
    private void setTableData(final File[] files) {
361  
        SwingUtilities.invokeLater(new Runnable() {
362  
            public void run() {
363  
                if (fileTableModel==null) {
364  
                    fileTableModel = new FileTableModel();
365  
                    table.setModel(fileTableModel);
366  
                }
367  
                table.getSelectionModel().removeListSelectionListener(listSelectionListener);
368  
                fileTableModel.setFiles(files);
369  
                table.getSelectionModel().addListSelectionListener(listSelectionListener);
370  
                if (!cellSizesSet) {
371  
                    Icon icon = fileSystemView.getSystemIcon(files[0]);
372  
373  
                    // size adjustment to better account for icons
374  
                    table.setRowHeight( icon.getIconHeight()+rowIconPadding );
375  
376  
                    setColumnWidth(0,-1);
377  
                    setColumnWidth(3,60);
378  
                    table.getColumnModel().getColumn(3).setMaxWidth(120);
379  
                    setColumnWidth(4,-1);
380  
                    setColumnWidth(5,-1);
381  
                    setColumnWidth(6,-1);
382  
                    setColumnWidth(7,-1);
383  
                    setColumnWidth(8,-1);
384  
                    setColumnWidth(9,-1);
385  
386  
                    cellSizesSet = true;
387  
                }
388  
            }
389  
        });
390  
    }
391  
392  
    private void setColumnWidth(int column, int width) {
393  
        TableColumn tableColumn = table.getColumnModel().getColumn(column);
394  
        if (width<0) {
395  
            // use the preferred width of the header..
396  
            JLabel label = new JLabel( (String)tableColumn.getHeaderValue() );
397  
            Dimension preferred = label.getPreferredSize();
398  
            // altered 10->14 as per camickr comment.
399  
            width = (int)preferred.getWidth()+14;
400  
        }
401  
        tableColumn.setPreferredWidth(width);
402  
        tableColumn.setMaxWidth(width);
403  
        tableColumn.setMinWidth(width);
404  
    }
405  
406  
    /** Add the files that are contained within the directory of this node.
407  
    Thanks to Hovercraft Full Of Eels for the SwingWorker fix. */
408  
    private void showChildren(final DefaultMutableTreeNode node) {
409  
        tree.setEnabled(false);
410  
        progressBar.setVisible(true);
411  
        progressBar.setIndeterminate(true);
412  
413  
        SwingWorker<Void, File> worker = new SwingWorker<Void, File>() {
414  
            @Override
415  
            public Void doInBackground() {
416  
                File file = (File) node.getUserObject();
417  
                if (file.isDirectory()) {
418  
                    File[] files = fileSystemView.getFiles(file, true); //!!
419  
                    if (node.isLeaf()) {
420  
                        for (File child : files) {
421  
                            if (child.isDirectory()) {
422  
                                publish(child);
423  
                            }
424  
                        }
425  
                    }
426  
                    setTableData(files);
427  
                }
428  
                return null;
429  
            }
430  
431  
            @Override
432  
            protected void process(List<File> chunks) {
433  
                for (File child : chunks) {
434  
                    node.add(new DefaultMutableTreeNode(child));
435  
                }
436  
            }
437  
438  
            @Override
439  
            protected void done() {
440  
                progressBar.setIndeterminate(false);
441  
                progressBar.setVisible(false);
442  
                tree.setEnabled(true);
443  
            }
444  
        };
445  
        worker.execute();
446  
    }
447  
448  
    /** Update the File details view with the details of this File. */
449  
    private void setFileDetails(File file) {
450  
        currentFile = file;
451  
        Icon icon = fileSystemView.getSystemIcon(file);
452  
        fileName.setIcon(icon);
453  
        fileName.setText(fileSystemView.getSystemDisplayName(file));
454  
        path.setText(file.getPath());
455  
        date.setText(new Date(file.lastModified()).toString());
456  
        size.setText(file.length() + " bytes");
457  
        readable.setSelected(file.canRead());
458  
        writable.setSelected(file.canWrite());
459  
        executable.setSelected(file.canExecute());
460  
        isDirectory.setSelected(file.isDirectory());
461  
462  
        isFile.setSelected(file.isFile());
463  
464  
        JFrame f = (JFrame)gui.getTopLevelAncestor();
465  
        if (f!=null) {
466  
            f.setTitle(
467  
                APP_TITLE +
468  
                " :: " +
469  
                fileSystemView.getSystemDisplayName(file) );
470  
        }
471  
472  
        gui.repaint();
473  
    }
474  
475  
    public static void main(String[] args) {
476  
        SwingUtilities.invokeLater(new Runnable() {
477  
            public void run() {
478  
                /*try {
479  
                    // Significantly improves the look of the output in
480  
                    // terms of the file names returned by FileSystemView!
481  
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
482  
                } catch(Exception weTried) {
483  
                }*/
484  
                JFrame f = new JFrame(APP_TITLE);
485  
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
486  
487  
                FileBrowser FileBrowser = new FileBrowser();
488  
                f.setContentPane(FileBrowser.getGui());
489  
490  
                try {
491  
                    URL urlBig = FileBrowser.getClass().getResource("fb-icon-32x32.png");
492  
                    URL urlSmall = FileBrowser.getClass().getResource("fb-icon-16x16.png");
493  
                    ArrayList<Image> images = new ArrayList<Image>();
494  
                    images.add( ImageIO.read(urlBig) );
495  
                    images.add( ImageIO.read(urlSmall) );
496  
                    f.setIconImages(images);
497  
                } catch(Exception weTried) {}
498  
499  
                f.pack();
500  
                f.setLocationByPlatform(true);
501  
                f.setMinimumSize(f.getSize());
502  
                f.setVisible(true);
503  
504  
                FileBrowser.showRootFile();
505  
            }
506  
        });
507  
    }
508  
}
509  
510  
/** A TableModel to hold File[]. */
511  
sclass FileTableModel extends AbstractTableModel {
512  
513  
    private File[] files;
514  
    private FileSystemView fileSystemView = FileSystemView.getFileSystemView();
515  
    private String[] columns = {
516  
        "Icon",
517  
        "File",
518  
        "Path/name",
519  
        "Size",
520  
        "Last Modified",
521  
        "R",
522  
        "W",
523  
        "E",
524  
        "D",
525  
        "F",
526  
    };
527  
528  
    FileTableModel() {
529  
        this(new File[0]);
530  
    }
531  
532  
    FileTableModel(File[] files) {
533  
        this.files = files;
534  
    }
535  
536  
    public Object getValueAt(int row, int column) {
537  
        File file = files[row];
538  
        switch (column) {
539  
            case 0:
540  
                return fileSystemView.getSystemIcon(file);
541  
            case 1:
542  
                return fileSystemView.getSystemDisplayName(file);
543  
            case 2:
544  
                return file.getPath();
545  
            case 3:
546  
                return file.length();
547  
            case 4:
548  
                return file.lastModified();
549  
            case 5:
550  
                return file.canRead();
551  
            case 6:
552  
                return file.canWrite();
553  
            case 7:
554  
                return file.canExecute();
555  
            case 8:
556  
                return file.isDirectory();
557  
            case 9:
558  
                return file.isFile();
559  
            default:
560  
                System.err.println("Logic Error");
561  
        }
562  
        return "";
563  
    }
564  
565  
    public int getColumnCount() {
566  
        return columns.length;
567  
    }
568  
569  
    public Class<?> getColumnClass(int column) {
570  
        switch (column) {
571  
            case 0:
572  
                return ImageIcon.class;
573  
            case 3:
574  
                return Long.class;
575  
            case 4:
576  
                return Date.class;
577  
            case 5:
578  
            case 6:
579  
            case 7:
580  
            case 8:
581  
            case 9:
582  
                return Boolean.class;
583  
        }
584  
        return String.class;
585  
    }
586  
587  
    public String getColumnName(int column) {
588  
        return columns[column];
589  
    }
590  
591  
    public int getRowCount() {
592  
        return files.length;
593  
    }
594  
595  
    public File getFile(int row) {
596  
        return files[row];
597  
    }
598  
599  
    public void setFiles(File[] files) {
600  
        this.files = files;
601  
        fireTableDataChanged();
602  
    }
603  
}
604  
605  
/** A TreeCellRenderer for a File. */
606  
sclass FileTreeCellRenderer extends DefaultTreeCellRenderer {
607  
608  
    private FileSystemView fileSystemView;
609  
610  
    private JLabel label;
611  
612  
    FileTreeCellRenderer() {
613  
        label = new JLabel();
614  
        label.setOpaque(true);
615  
        fileSystemView = FileSystemView.getFileSystemView();
616  
    }
617  
618  
    @Override
619  
    public Component getTreeCellRendererComponent(
620  
        JTree tree,
621  
        Object value,
622  
        boolean selected,
623  
        boolean expanded,
624  
        boolean leaf,
625  
        int row,
626  
        boolean hasFocus) {
627  
628  
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)value;
629  
        File file = (File)node.getUserObject();
630  
        label.setIcon(fileSystemView.getSystemIcon(file));
631  
        label.setText(fileSystemView.getSystemDisplayName(file));
632  
        label.setToolTipText(file.getPath());
633  
634  
        if (selected) {
635  
            label.setBackground(backgroundSelectionColor);
636  
            label.setForeground(textSelectionColor);
637  
        } else {
638  
            label.setBackground(backgroundNonSelectionColor);
639  
            label.setForeground(textNonSelectionColor);
640  
        }
641  
642  
        return label;
643  
    }
644  
}

download  show line numbers  debug dex  old transpilations   

Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1006655
Snippet name: FileBro [works, but interface has little quirks]
Eternal ID of this version: #1006655/1
Text MD5: 24d2b76fe5c159b8eabd567a8322b743
Transpilation MD5: 00949d6518c9cb43b557cd53d048184f
Author: stefan
Category: javax / gui
Type: JavaX source code
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2017-01-31 05:56:21
Source code size: 22138 bytes / 644 lines
Pitched / IR pitched: No / No
Views / Downloads: 420 / 534
Referenced in: [show references]