/*
* Copyright 2012 jMethods, Inc.
*
* 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.myjavaworld.jftp;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Vector;
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import com.myjavaworld.gui.DateCellRenderer;
import com.myjavaworld.gui.GUIUtil;
import com.myjavaworld.gui.IndentIcon;
import com.myjavaworld.gui.MButton;
import com.myjavaworld.gui.MComboBox;
import com.myjavaworld.gui.MLabel;
import com.myjavaworld.gui.MScrollPane;
import com.myjavaworld.gui.MTable;
import com.myjavaworld.gui.MTableCellRenderer;
import com.myjavaworld.gui.MTableHeaderRenderer;
import com.myjavaworld.gui.NumericCellRenderer;
import com.myjavaworld.jftp.actions.DeleteLocalFileAction;
import com.myjavaworld.jftp.actions.OpenLocalFileAction;
import com.myjavaworld.util.ResourceLoader;
/**
* Local File System view.
*
* @author Sai Pullabhotla, psai [at] jMethods [dot] com
* @version 2.0
*
*/
public class LocalPane extends JPanel implements ActionListener, MouseListener,
ListSelectionListener {
private static ResourceBundle resources = ResourceLoader
.getBundle("com.myjavaworld.jftp.LocalPane");
private static final Icon UP_ARROW_ICON = JFTPUtil.getIcon("upArrow16.gif");
private static final Icon DOWN_ARROW_ICON = JFTPUtil
.getIcon("downArrow16.gif");
private FTPSession session = null;
private MComboBox comboRoots = null;
private MComboBox comboWorkingDirectory = null;
private MButton butUp = null;
private LocalFileTableModel model = null;
private MTable table = null;
private MScrollPane scroller = null;
private MLabel labStatus = null;
private LocalFileComparator comparator = null;
private boolean updateComboWorkingDirectory = true;
private MessageFormat statusFormat1 = null;
private MessageFormat statusFormat2 = null;
private Object[] statusArgs = null;
private DirectoryComboBoxModel dcm = null;
public LocalPane(FTPSession session) {
super();
this.session = session;
comparator = new LocalFileComparator();
statusFormat1 = new MessageFormat(
resources.getString("status.objectCount"));
statusFormat2 = new MessageFormat(
resources.getString("status.selectedObjectCount"));
statusFormat1.setLocale(Locale.getDefault());
statusFormat2.setLocale(Locale.getDefault());
statusArgs = new Object[2];
setLayout(new GridBagLayout());
initComponents();
configureTable();
updateTableHeader();
}
public void setData(LocalFile dir, LocalFile[] data) {
if (data == null) {
return;
}
if (dcm == null) {
dcm = new DirectoryComboBoxModel(dir);
comboWorkingDirectory.setModel(dcm);
comboWorkingDirectory.setRenderer(new DirectoryCellRenderer());
}
Arrays.sort(data, comparator);
model.setData(data);
if (updateComboWorkingDirectory) {
updateComboWorkingDirectory(dir);
}
if (data.length > 0) {
table.scrollRectToVisible(table.getCellRect(0, 0, true));
}
updateStatus();
}
public LocalFile[] getData() {
return model.getData();
}
public int getSelectionCount() {
return table.getSelectedRowCount();
}
public LocalFile getSelectedFile() {
int row = table.getSelectedRow();
if (row < 0) {
return null;
}
return model.getFileAt(row);
}
public LocalFile[] getSelectedFiles() {
int[] selectedRows = table.getSelectedRows();
if (selectedRows == null) {
return new LocalFile[0];
}
LocalFile[] selectedFiles = new LocalFile[selectedRows.length];
for (int i = 0; i < selectedRows.length; i++) {
selectedFiles[i] = model.getFileAt(selectedRows[i]);
}
return selectedFiles;
}
public void refresh() {
session.setLocalWorkingDirectory(session.getLocalWorkingDirectory());
comboRoots.setModel(new DefaultComboBoxModel(getRoots()));
}
public void valueChanged(ListSelectionEvent evt) {
updateStatus();
session.updateToolBar();
}
public void actionPerformed(ActionEvent evt) {
if (evt.getSource() == butUp) {
session.upLocalWorkingDirectory();
} else if (evt.getSource() == comboRoots) {
LocalFile root = (LocalFile) comboRoots.getSelectedItem();
if (root == null) {
return;
}
session.setLocalWorkingDirectory(root);
} else if (evt.getSource() == comboWorkingDirectory) {
LocalFile selectedFile = (LocalFile) comboWorkingDirectory
.getSelectedItem();
updateComboWorkingDirectory = false;
session.setLocalWorkingDirectory(selectedFile);
updateComboWorkingDirectory = true;
}
}
public void mouseEntered(MouseEvent evt) {
}
public void mouseExited(MouseEvent evt) {
}
public void mousePressed(MouseEvent evt) {
if (evt.isPopupTrigger()) {
if (evt.getSource() == table) {
tableRightClicked(evt);
} else if (evt.getSource() == scroller) {
scrollerRightClicked(evt);
}
}
}
public void mouseReleased(MouseEvent evt) {
if (evt.isPopupTrigger()) {
if (evt.getSource() == table) {
tableRightClicked(evt);
} else if (evt.getSource() == scroller) {
scrollerRightClicked(evt);
}
} else if (evt.getSource() == table) {
if (SwingUtilities.isLeftMouseButton(evt)
&& evt.getClickCount() >= 2) {
doubleClicked(evt);
}
} else if (evt.getSource() == table.getTableHeader()) {
if (SwingUtilities.isLeftMouseButton(evt)) {
Cursor cursor = table.getTableHeader().getCursor();
if (cursor.equals(Cursor
.getPredefinedCursor(Cursor.DEFAULT_CURSOR))) {
int column = table.columnAtPoint(evt.getPoint());
column = table.convertColumnIndexToModel(column);
sort(column);
}
}
}
}
public void mouseClicked(MouseEvent evt) {
}
private void tableRightClicked(MouseEvent evt) {
JPopupMenu popup = LocalSystemPopupMenu.getInstance(session.getJFTP());
popup.show((Component) evt.getSource(), evt.getX(), evt.getY());
}
private void scrollerRightClicked(MouseEvent evt) {
table.clearSelection();
JPopupMenu popup = LocalSystemPopupMenu.getInstance(session.getJFTP());
popup.show((Component) evt.getSource(), evt.getX(), evt.getY());
}
private void doubleClicked(MouseEvent evt) {
int row = table.rowAtPoint(evt.getPoint());
if (row < 0) {
return;
}
LocalFile file = model.getFileAt(row);
OpenLocalFileAction.getInstance(session.getJFTP())
.actionPerformed(null);
}
private LocalFile[] getRoots() {
LocalFile[] roots = LocalFile.listRoots();
if (roots == null) {
roots = new LocalFile[0];
}
return roots;
}
private void updateComboWorkingDirectory(LocalFile dir) {
comboWorkingDirectory.removeActionListener(this);
dcm.addItem(dir);
dcm.setSelectedItem(dir);
comboWorkingDirectory.addActionListener(this);
}
private void updateStatus() {
long size = 0L;
int count = table.getSelectedRowCount();
if (count > 0) {
int[] selectedRows = table.getSelectedRows();
for (int i = 0; i < selectedRows.length; i++) {
size += model.getFileAt(selectedRows[i]).getSize();
}
statusArgs[0] = new Integer(count);
statusArgs[1] = new Long(size);
// statusArgs[2] = new Integer(count);
labStatus.setText(statusFormat2.format(statusArgs));
return;
}
count = model.getRowCount();
for (int i = 0; i < count; i++) {
size += model.getFileAt(i).getSize();
}
statusArgs[0] = new Integer(count);
statusArgs[1] = new Long(size);
// statusArgs[2] = new Integer(count);
labStatus.setText(statusFormat1.format(statusArgs));
}
private void sort(int col) {
int compareBy = comparator.getCompareBy();
int order = comparator.getOrder();
if (compareBy == col + 1) {
order = order == LocalFileComparator.ASC_ORDER ? LocalFileComparator.DESC_ORDER
: LocalFileComparator.ASC_ORDER;
} else {
compareBy = col + 1;
order = LocalFileComparator.ASC_ORDER;
}
comparator.setCompareBy(compareBy);
comparator.setOrder(order);
LocalFile[] data = model.getData();
Arrays.sort(model.getData(), comparator);
model.setData(data);
updateTableHeader();
}
private void updateTableHeader() {
int compareBy = comparator.getCompareBy();
int order = comparator.getOrder();
Icon icon = order == LocalFileComparator.ASC_ORDER ? UP_ARROW_ICON
: DOWN_ARROW_ICON;
for (int i = 0; i < 4; i++) {
MTableHeaderRenderer r = new MTableHeaderRenderer();
if (compareBy - 1 == i) {
r.setIcon(icon);
} else {
r.setIcon(null);
}
table.getColumnModel().getColumn(table.convertColumnIndexToView(i))
.setHeaderRenderer(r);
}
}
private void initComponents() {
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.WEST;
comboRoots = new MComboBox(getRoots());
comboRoots.setRenderer(new DriveCellRenderer());
// comboRoots.setData(getRoots());
comboRoots.setToolTipText(resources.getString("tooltip.roots"));
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 0.0;
c.weighty = 0.0;
c.fill = GridBagConstraints.NONE;
c.insets = new Insets(2, 0, 2, 2);
add(comboRoots, c);
comboWorkingDirectory = new MComboBox();
comboWorkingDirectory.setToolTipText(resources
.getString("tooltip.workingDirectory"));
comboWorkingDirectory.addActionListener(this);
c.gridx = 1;
c.gridy = 0;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 1.0;
c.weighty = 0.0;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(2, 0, 2, 2);
add(comboWorkingDirectory, c);
// butUp = new MButton(UIManager.getIcon("FileChooser.upFolderIcon"));
butUp = new MButton(JFTPUtil.getIcon("upDirectory16.gif"));
butUp.setToolTipText(resources.getString("tooltip.up"));
butUp.addActionListener(this);
c.gridx = 2;
c.gridy = 0;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 0.0;
c.weighty = 0.0;
c.fill = GridBagConstraints.NONE;
c.insets = new Insets(2, 0, 2, 0);
add(butUp, c);
model = new LocalFileTableModel();
table = new MTable(model) {
@Override
public boolean getScrollableTracksViewportWidth() {
return (getPreferredSize().width < getParent().getWidth());
}
};
table.setShowGrid(false);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
scroller = new MScrollPane(table);
if (table.isBackgroundSet()) {
scroller.getViewport().setBackground(table.getBackground());
}
c.gridx = 0;
c.gridy = 1;
c.gridwidth = 3;
c.gridheight = 1;
c.weightx = 1.0;
c.weighty = 1.0;
c.fill = GridBagConstraints.BOTH;
c.insets = new Insets(0, 0, 2, 0);
add(scroller, c);
labStatus = new MLabel("Status Bar");
c.gridx = 0;
c.gridy = 2;
c.gridwidth = 3;
c.gridheight = 1;
c.weightx = 1.0;
c.weighty = 0.0;
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(0, 5, 2, 0);
add(labStatus, c);
comboRoots.addActionListener(this);
}
private void configureTable() {
table.setName("localPane");
scroller.setName("localPane");
TransferHandler th = new DnDTransferHandler(session.getJFTP());
table.setDragEnabled(true);
scroller.setTransferHandler(th);
table.setTransferHandler(th);
table.getColumnModel().getColumn(0).setPreferredWidth(150);
table.getColumnModel().getColumn(1).setPreferredWidth(75);
table.getColumnModel().getColumn(2).setPreferredWidth(100);
table.getColumnModel().getColumn(3).setPreferredWidth(150);
table.setDefaultRenderer(LocalFile.class, new LocalFileCellRenderer());
table.setDefaultRenderer(Long.class, new NumericCellRenderer());
int dateFormat = JFTP.prefs.getDateFormat();
int timeFormat = JFTP.prefs.getTimeFormat();
table.setDefaultRenderer(Date.class, new DateCellRenderer(dateFormat,
timeFormat));
table.setDefaultRenderer(Object.class, new MTableCellRenderer());
table.addMouseListener(this);
scroller.addMouseListener(this);
table.getSelectionModel().addListSelectionListener(this);
table.getTableHeader().setDefaultRenderer(new MTableHeaderRenderer());
table.getTableHeader().addMouseListener(this);
table.registerKeyboardAction(
DeleteLocalFileAction.getInstance(session.getJFTP()),
"cmd.deleteLocalFile",
KeyStroke.getKeyStroke(GUIUtil.getDeleteKey(), 0),
JComponent.WHEN_FOCUSED);
table.registerKeyboardAction(
OpenLocalFileAction.getInstance(session.getJFTP()),
"cmd.openLocalFile",
KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0),
JComponent.WHEN_FOCUSED);
}
class DirectoryComboBoxModel extends AbstractListModel implements
ComboBoxModel {
private LocalFile selectedDir = null;
private Vector dirs = null;
public DirectoryComboBoxModel(LocalFile dir) {
dirs = new Vector(10);
this.selectedDir = dir;
// addI
}
public Object getSelectedItem() {
return selectedDir;
}
public void setSelectedItem(Object selectedDir) {
this.selectedDir = (LocalFile) selectedDir;
fireContentsChanged(this, -1, -1);
}
public int getSize() {
return dirs.size();
}
public Object getElementAt(int index) {
return dirs.get(index);
}
private void addItem(LocalFile dir) {
if (dir == null) {
return;
}
LocalFile cdir = dir;
try {
cdir = dir.getCanonicalFile();
} catch (IOException exp) {
}
dirs.clear();
do {
dirs.add(0, cdir);
} while ((cdir = cdir.getParent()) != null);
}
}
class DirectoryCellRenderer extends MLabel implements ListCellRenderer {
private IndentIcon indentIcon = null;
public DirectoryCellRenderer() {
super();
setOpaque(true);
indentIcon = new IndentIcon();
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
LocalFile lf = (LocalFile) value;
// if(lf == null) {
// setText("null");
// return this;
// }
setText(lf.getDisplayName());
indentIcon.setIcon(lf.getIcon());
indentIcon.setDepth(index + 1);
setIcon(indentIcon);
setBackground(isSelected ? list.getSelectionBackground() : list
.getBackground());
setForeground(isSelected ? list.getSelectionForeground() : list
.getForeground());
setFont(list.getFont());
return this;
}
}
public void selectAll() {
table.selectAll();
}
public void invertSelection() {
int rowCount = model.getRowCount();
ListSelectionModel selectionModel = table.getSelectionModel();
for (int i = 0; i < rowCount; i++) {
if (selectionModel.isSelectedIndex(i)) {
selectionModel.removeSelectionInterval(i, i);
} else {
selectionModel.addSelectionInterval(i, i);
}
}
}
}