package ru.kkey.ui;
import ru.kkey.ui.menu.*;
import ru.kkey.ui.preview.CloseAction;
import ru.kkey.ui.preview.Preview;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* View for the application window
*
* @author anstarovoyt
* @see FilesController
*/
public class FilesView
{
public static final String MENU_ITEM_LOCATION = "location";
public static final String MENU_ITEM_ZIP = "zip";
public static final String MENU_ITEM_FTP = "ftp";
private static final String HOME_KEY = "home";
private static final String END_KEY = "end";
private final Map<String, MenuAction> menuActions = new LinkedHashMap<>();
{
menuActions.put(MENU_ITEM_LOCATION, new OpenLocationAction());
menuActions.put(MENU_ITEM_ZIP, new OpenZipAction());
menuActions.put(MENU_ITEM_FTP, new OpenFTPAction());
}
private final DefaultTableModel tableModel = new DefaultTableModel()
{
private static final long serialVersionUID = 1L;
@Override
public boolean isCellEditable(int row, int column)
{
return false;
}
};
private final JFrame mainFrame;
private final JMenuBar menuBar;
private final JTable table;
private final JLabel stateMessage;
private final JDialog dialog;
//process only in dispatch thread -> no volatile
private JPanel contentDialogPanel;
public FilesView()
{
mainFrame = createMainFrame();
menuBar = createMenu();
table = createTable();
stateMessage = createStateField();
dialog = createDialog();
//vertical presentation
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
mainFrame.setJMenuBar(menuBar);
mainFrame.add(panel);
panel.add(packToScrollablePane(table));
panel.add(stateMessage);
customizeRowStyle();
bindHomeKey();
bindEndKey();
}
public void addActionForMenu(String item, SelectMenuResult result)
{
menuActions.get(item).bind(mainFrame, result);
}
public void addKeySelectionListener(KeyStroke key, String code, Action action)
{
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(key, code);
table.getActionMap().put(code, action);
}
public void addMouseListener(MouseListener adapter)
{
table.addMouseListener(adapter);
}
@SuppressWarnings("unchecked")
public <T> T getSelectedValue()
{
return -1 == table.getSelectedRow() ? null : (T) table.getValueAt(table.getSelectedRow(), 0);
}
public int getValueIndex(List<?> data, Object item)
{
if (null == item)
{
return 0;
}
int valueIndex = data.indexOf(item);
if (valueIndex < 0)
{
return 0;
}
return valueIndex;
}
public boolean isSelectedBackLink()
{
return table.getSelectedRow() == 0;
}
public void resetStateMessage()
{
stateMessage.setText(" ");
}
public void setFilesAndUpdateView(java.util.List<?> files, Object selectedItem)
{
tableModel.getDataVector().clear();
table.clearSelection();
for (Object item : files)
{
tableModel.addRow(new Object[]{item});
}
tableModel.fireTableDataChanged();
table.requestFocus();
int selectionIndex = getValueIndex(files, selectedItem);
table.changeSelection(selectionIndex, 0, false, false);
}
public void setStateMessage(String newState)
{
stateMessage.setText(newState);
}
public void show()
{
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
public void showDialog(Preview preview, byte[] file)
{
try
{
contentDialogPanel = new JPanel();
contentDialogPanel.setLayout(new BorderLayout());
dialog.add(contentDialogPanel);
dialog.setSize(new Dimension(800, 600));
dialog.setLocationRelativeTo(null);
preview.render(contentDialogPanel, file);
dialog.revalidate();
dialog.repaint();
dialog.setVisible(true);
} catch (RuntimeException e)
{
dialog.dispose();
cleanDialog();
throw e;
}
}
private void bindEndKey()
{
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_END, 0);
addKeySelectionListener(enter, END_KEY, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e)
{
int rowNum = table.getRowCount() - 1;
if (rowNum < 0)
{
return;
}
setFocusToRow(rowNum);
}
});
}
private void bindHomeKey()
{
KeyStroke enter = KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0);
addKeySelectionListener(enter, HOME_KEY, new AbstractAction()
{
private static final long serialVersionUID = 1L;
@Override
public void actionPerformed(ActionEvent e)
{
setFocusToRow(0);
}
});
}
private JDialog createDialog()
{
JDialog dialog = new JDialog(mainFrame, true);
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter()
{
@Override
public void windowClosing(WindowEvent e)
{
cleanDialog();
}
});
dialog.setSize(new Dimension(800, 600));
CloseAction.bindToEsc(dialog);
return dialog;
}
private void cleanDialog()
{
if (null != contentDialogPanel)
{
dialog.remove(contentDialogPanel);
contentDialogPanel = null;
dialog.revalidate();
}
}
private JFrame createMainFrame()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(new Dimension(700, 500));
frame.setTitle("Simple file manager");
return frame;
}
private JMenuBar createMenu()
{
JMenuBar bar = new JMenuBar();
JMenu menu = new JMenu("File");
bar.add(menu);
for (Map.Entry<String, MenuAction> entry : menuActions.entrySet())
{
JMenuItem menuItem = new JMenuItem(entry.getValue().getName());
menuItem.addActionListener(entry.getValue());
menu.add(menuItem);
}
return bar;
}
private JLabel createStateField()
{
JLabel state = new JLabel();
state.setText(" ");
state.setLayout(new BorderLayout());
state.setHorizontalAlignment(SwingConstants.LEFT);
return state;
}
private JTable createTable()
{
JTable table = new JTable(tableModel);
table.setGridColor(new Color(0, 0, 0));
table.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
return table;
}
private void customizeRowStyle()
{
tableModel.addColumn("File list");
table.setFont(new Font(table.getFont().getFontName(), 0, 15));
table.setRowHeight(20);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
private JComponent packToScrollablePane(JComponent component)
{
JScrollPane jScrollPane = new JScrollPane(component);
jScrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
return jScrollPane;
}
private void setFocusToRow(int rowNum)
{
table.requestFocus();
table.changeSelection(rowNum, 0, false, false);
}
}