/****************************************************************************** * * * Copyright 2016 Subterranean Security * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * * *****************************************************************************/ package com.subterranean_security.crimson.viewer.ui.screen.files; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.Comparator; import javax.swing.ImageIcon; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingConstants; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableRowSorter; import com.subterranean_security.crimson.core.util.UnitTranslator; import com.subterranean_security.crimson.viewer.ui.UIUtil; public class FileTable extends JPanel { private static final long serialVersionUID = 1L; public TM tm = new TM(); public TR tr = new TR(tm); private JTable table = new JTable(); public Pane pane; public FileTable(Pane parent) { pane = parent; initContextMenu(); init(); initRowSorter(); } public ArrayList<FileItem> selection = null; public void init() { setLayout(new BorderLayout()); table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { if (pane.loading) { return; } // switch path to view if needed pane.pwd.openView(); // get source of click JTable source = (JTable) e.getSource(); final int sourceRow = source.rowAtPoint(e.getPoint()); pane.btnProperties.setEnabled(sourceRow != -1); pane.btnDelete.setEnabled(sourceRow != -1); if (sourceRow == -1) { source.clearSelection(); return; } // select row or go down if (!source.isRowSelected(sourceRow)) { source.changeSelection(sourceRow, 0, false, false); } selection = new ArrayList<FileItem>(); for (int i : source.getSelectedRows()) { selection.add(tm.getFile(i)); } if (e.getButton() == MouseEvent.BUTTON3) { initContextActions(); popup.show(table, e.getPoint().x, e.getPoint().y); } else if (e.getButton() == MouseEvent.BUTTON1 && e.getClickCount() == 2) { if (tm.getFile(sourceRow).isFolder()) { pane.down(tm.getFile(sourceRow).getIcon().getDescription()); } return; } } }); table.setShowHorizontalLines(false); table.setShowVerticalLines(false); table.setFillsViewportHeight(true); table.setDefaultRenderer(Object.class, tr); table.setModel(tm); JScrollPane jsp = new JScrollPane(table); add(jsp, BorderLayout.CENTER); } JPopupMenu popup; JMenuItem menu_copy; JMenuItem menu_cut; JMenuItem menu_delete; JMenuItem menu_rename; JMenuItem menu_compress; JMenuItem menu_decompress; JMenuItem menu_properties; private void initContextMenu() { popup = new JPopupMenu(); menu_copy = new JMenuItem("Copy"); menu_copy.setIcon(UIUtil.getIcon("icons16/general/page_copy.png")); menu_cut = new JMenuItem("Cut"); menu_cut.setIcon(UIUtil.getIcon("icons16/general/cut.png")); menu_delete = new JMenuItem("Delete"); menu_delete.setIcon(UIUtil.getIcon("icons16/general/folder_delete.png")); menu_delete.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { pane.delete(selection); } }); menu_rename = new JMenuItem("Rename"); menu_rename.setIcon(UIUtil.getIcon("icons16/general/textfield_rename.png")); menu_compress = new JMenuItem("Compress"); menu_compress.setIcon(UIUtil.getIcon("icons16/general/compress.png")); menu_decompress = new JMenuItem("Decompress"); menu_decompress.setIcon(UIUtil.getIcon("icons16/general/server_uncompress.png")); menu_properties = new JMenuItem("Properties"); menu_properties.setIcon(UIUtil.getIcon("icons16/general/attributes_display.png")); menu_properties.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // TODO multi selection pane.info(selection.get(0).getIcon().getDescription()); } }); } private void initContextActions() { popup.removeAll(); if (selection.size() == 0) { return; } else if (selection.size() == 1) { popup.add(menu_rename); popup.add(menu_properties); } else { } popup.add(menu_copy); popup.add(menu_cut); popup.add(menu_delete); } public void setFiles(ArrayList<FileItem> list) { tm.setFiles(list); } private void initRowSorter() { TableRowSorter<TM> sorter = new TableRowSorter<TM>(tm); sorter.toggleSortOrder(0); // TODO hardcoded headers sorter.setComparator(0, new FileItem.NameComparator()); sorter.setComparator(1, new FileItem.SizeComparator()); table.setRowSorter(sorter); } } class TM extends AbstractTableModel { private static final long serialVersionUID = 1L; public String[] headers = new String[] { "Name", "Size" }; private ArrayList<FileItem> files = new ArrayList<FileItem>(); public void setFiles(ArrayList<FileItem> list) { files = list; this.fireTableDataChanged(); } @Override public int getColumnCount() { return headers.length; } @Override public int getRowCount() { return files.size(); } @Override public String getColumnName(int column) { return headers[column]; }; @Override public Object getValueAt(int rowIndex, int columnIndex) { return files.get(rowIndex); } public FileItem getFile(int row) { return files.get(row); } } class TR extends DefaultTableCellRenderer { private static final long serialVersionUID = 1L; private TM tm; public TR(TM tm) { this.tm = tm; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, setupCell(table, (FileItem) value, column), isSelected, hasFocus, row, column); return this; } /** * Setup and return the data for the given cell * * @param table * @param file * @param viewColumn * @return */ private Object setupCell(JTable table, FileItem file, int viewColumn) { setBorder(noFocusBorder); switch (tm.headers[table.convertColumnIndexToModel(viewColumn)]) { case "Name": { setHorizontalAlignment(SwingConstants.LEFT); return file.getIcon(); } case "Size": { setHorizontalAlignment(viewColumn == 0 ? SwingConstants.LEFT : SwingConstants.RIGHT); return file.getSize(); } } return null; } protected void setValue(Object value) { if (value instanceof ImageIcon) { ImageIcon ico = (ImageIcon) value; setIcon(ico); setText(ico.getDescription()); } else { setIcon(null); super.setValue(value); } } } class FileItem { private ImageIcon icon; private long size; private String sizeStr; private long mtime; private String mtimeStr; private boolean folder; public FileItem(String name, boolean dir, long size, long mtime) { this.mtime = mtime; this.size = size; this.folder = dir; if (dir) { this.sizeStr = size + ((size == 1) ? " item " : " items"); icon = UIUtil.getIcon("icons16/files/file_extension_folder.png"); } else { this.sizeStr = UnitTranslator.familiarize(size, UnitTranslator.BYTES); icon = UIUtil.getIcon("icons16/files/file_extension_" + name.substring(name.lastIndexOf('.') + 1) + ".png"); if (icon == null) { icon = UIUtil.getIcon("icons16/files/file_extension_default.png"); } } icon.setDescription(name); } public ImageIcon getIcon() { return icon; } public String getName() { return icon.getDescription(); } public String getSize() { return sizeStr; } public String getMtime() { return mtimeStr; } public boolean isFolder() { return folder; } static class NameComparator implements Comparator<FileItem> { @Override public int compare(FileItem o1, FileItem o2) { if (o1 == o2) { return 0; } else if (o1.folder && !o2.folder) { return -1; } else if (!o1.folder && o2.folder) { return 1; } return o1.getName().toLowerCase().compareTo(o2.getName().toLowerCase()); } } static class MTimeComparator implements Comparator<FileItem> { @Override public int compare(FileItem o1, FileItem o2) { return (int) (o1.mtime - o2.mtime); } } static class SizeComparator implements Comparator<FileItem> { @Override public int compare(FileItem o1, FileItem o2) { if (o1 == o2) { return 0; } else if (o1.folder && !o2.folder) { return -1; } else if (!o1.folder && o2.folder) { return 1; } return (int) (o1.size - o2.size); } } }