/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.kapti.administration;
import com.kapti.client.finance.Exchange;
import com.kapti.client.finance.FinanceFactory;
import com.kapti.client.finance.Security;
import com.kapti.administration.tablemodels.SecuritiesTableModel;
import com.kapti.client.finance.Index;
import com.kapti.exceptions.StockPlayException;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutionException;
import java.util.regex.Pattern;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import org.apache.log4j.Logger;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.swingx.JXErrorPane;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.HighlighterFactory;
import org.jdesktop.jxlayer.plaf.ext.LockableUI;
import org.jdesktop.swingx.error.ErrorInfo;
/**
*
* @author Thijs
*/
public class SecuritiesListPanel extends JPanel implements TableModelListener, ListSelectionListener, ActionListener {
private static final String REFRESH_ACTION = "REFRESH";
private static final String SHOW_SECURITY_ACTION = "SHOW_SECURITY";
private static final String HIDE_SECURITY_ACTION = "HIDE_SECURITY";
private static final String RESUME_SECURITY_ACTION = "RESUME_SECURITY";
private static final String SUSPEND_SECURITY_ACTION = "SUSPEND_SECURITY";
private static final String SAVE_ACTION = "SAVE";
private static Logger logger = Logger.getLogger(SecuritiesListPanel.class);
private FinanceFactory finFactory = FinanceFactory.getInstance();
private final ResourceBundle translations = ResourceBundle.getBundle("com/kapti/administration/translations");
private static SecuritiesListPanel instance = new SecuritiesListPanel();
private JLabel titleLabel = new JLabel(translations.getString("OVERVIEW"));
private JLabel selectedLabel = new JLabel(translations.getString("SELECTED_SECURITIES_COUNT") + " 0");
private LockableUI lockUI = null;
private JXLayer<JComponent> busyLayer = null;
private JXTable securitiesTable = null;
private SecuritiesTableModel securitiesTableModel = null;
private JButton showSecurity = new JButton(translations.getString("SHOW_SECURITY"));
private JButton hideSecurity = new JButton(translations.getString("HIDE_SECURITY"));
private JButton resumeSecurity = new JButton(translations.getString("RESUME_SECURITY"));
private JButton suspendSecurity = new JButton(translations.getString("SUSPEND_SECURITY"));
private JButton saveButton = new JButton(translations.getString("SAVE") + " (0)");
private JButton refreshButton = new JButton(translations.getString("REFRESH"));
//filtering
private ExchangeRowFilter exchangeRowFilter = null;
private IndexRowFilter indexRowFilter = null;
private StringRowFilter stringRowFilter = null;
private JLabel searchLabel = new JLabel(translations.getString("SEARCH_SECURITY"));
private JTextField searchField = new JTextField();
public static SecuritiesListPanel getInstance() {
return instance;
}
private SecuritiesListPanel() {
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 30));
add(titleLabel, BorderLayout.NORTH);
//We stellen hier onze securities-JXTable in
securitiesTableModel = new SecuritiesTableModel();
securitiesTable = new JXTable(securitiesTableModel);
securitiesTable.setColumnControlVisible(true);
securitiesTable.setShowGrid(false, false);
securitiesTable.setHighlighters(HighlighterFactory.createAlternateStriping());
securitiesTable.setAutoCreateRowSorter(true);
securitiesTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
securitiesTable.getSelectionModel().addListSelectionListener(this);
securitiesTableModel.addTableModelListener(this);
TableColumn exchangeColumn = securitiesTable.getColumn(2);
JComboBox exchangesComboBox = new JComboBox();
try {
for (Exchange exch : finFactory.getAllExchanges()) {
exchangesComboBox.addItem(exch);
}
} catch (StockPlayException ex) {
JXErrorPane.showDialog(new Exception(translations.getString("ERROR_RENDERING_SECURITIESCOMBOBOX"), ex));
}
exchangeColumn.setCellEditor(new DefaultCellEditor(exchangesComboBox));
JScrollPane securitiesTableScrollPane = new JScrollPane(securitiesTable);
//we voegen de tabel toe aan de busylayer, zodat deze kan blokkeren tijdens het inladen
lockUI = new LockableUI();
busyLayer = new JXLayer<JComponent>(securitiesTableScrollPane, lockUI);
busyLayer.setUI(lockUI);
add(busyLayer, BorderLayout.CENTER);
lockUI.setLocked(true);
searchField.getDocument().addDocumentListener(new DocumentListener() {
private void updateSearchFilter() {
if (searchField.getText().length() > 0) {
stringRowFilter = new StringRowFilter(searchField.getText());
} else {
stringRowFilter = null;
}
updateFilters();
}
public void insertUpdate(DocumentEvent e) {
updateSearchFilter();
}
public void removeUpdate(DocumentEvent e) {
updateSearchFilter();
}
public void changedUpdate(DocumentEvent e) {
//niet nodig
}
});
//de onderste balk
add(new SecuritiesListActionPanel(), BorderLayout.SOUTH);
//we stellen de acties in
refreshButton.setActionCommand(REFRESH_ACTION);
refreshButton.addActionListener(this);
showSecurity.setActionCommand(SHOW_SECURITY_ACTION);
showSecurity.addActionListener(this);
hideSecurity.setActionCommand(HIDE_SECURITY_ACTION);
hideSecurity.addActionListener(this);
resumeSecurity.setActionCommand(RESUME_SECURITY_ACTION);
resumeSecurity.addActionListener(this);
suspendSecurity.setActionCommand(SUSPEND_SECURITY_ACTION);
suspendSecurity.addActionListener(this);
saveButton.setActionCommand(SAVE_ACTION);
saveButton.addActionListener(this);
saveButton.setEnabled(false);
//we laden hier onze gegevens in
fetchSecuritiesTable();
}
public void tableChanged(TableModelEvent e) {
checkButtons();
}
public void valueChanged(ListSelectionEvent e) {
selectedLabel.setText(translations.getString("SELECTED_SECURITIES_COUNT") + " " + securitiesTable.getSelectedRowCount());
checkButtons();
}
private void checkButtons() {
boolean show = false, hide = false, resume = false, suspend = false;
for (int rowIndex : securitiesTable.getSelectedRows()) {
Security sec = securitiesTableModel.getSecurityAt(rowIndex);
if (sec.isVisible()) {
hide = true;
} else {
show = true;
}
if (sec.isSuspended()) {
resume = true;
} else {
suspend = true;
}
}
showSecurity.setEnabled(show);
hideSecurity.setEnabled(hide);
resumeSecurity.setEnabled(resume);
suspendSecurity.setEnabled(suspend);
saveButton.setText(translations.getString("SAVE") + " (" + securitiesTableModel.getChangedRowsCount() + ")");
saveButton.setEnabled(securitiesTableModel.getChangedRowsCount() > 0);
}
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(REFRESH_ACTION)) {
fetchSecuritiesTable();
} else if (e.getActionCommand().equals(SHOW_SECURITY_ACTION)) {
for (int rownr : securitiesTable.getSelectedRows()) {
Security sec = securitiesTableModel.getSecurityAt(rownr);
sec.setVisible(true);
}
} else if (e.getActionCommand().equals(HIDE_SECURITY_ACTION)) {
for (int rownr : securitiesTable.getSelectedRows()) {
Security sec = securitiesTableModel.getSecurityAt(rownr);
sec.setVisible(false);
}
} else if (e.getActionCommand().equals(RESUME_SECURITY_ACTION)) {
for (int rownr : securitiesTable.getSelectedRows()) {
Security sec = securitiesTableModel.getSecurityAt(rownr);
sec.setSuspended(false);
}
} else if (e.getActionCommand().equals(SUSPEND_SECURITY_ACTION)) {
for (int rownr : securitiesTable.getSelectedRows()) {
Security sec = securitiesTableModel.getSecurityAt(rownr);
sec.setSuspended(true);
}
} else if (e.getActionCommand().equals(SAVE_ACTION)) {
for (Security sec : securitiesTableModel.getSecurities()) {
try {
if (!finFactory.makePersistent(sec)) {
throw new StockPlayException("Saving securities failed");
}
} catch (StockPlayException ex) {
logger.error(translations.getString("ERROR_SAVING_SECURITY"), ex);
JXErrorPane.showDialog(null, new ErrorInfo(translations.getString("ERROR"), translations.getString("ERROR_SAVING_SECURITIES"), "", "", null, null, null));
}
}
securitiesTableModel.setChangesSaved();
}
}
private void fetchSecuritiesTable() {
SwingWorker<Collection<Security>, Void> worker = new SwingWorker<Collection<Security>, Void>() {
@Override
protected Collection<Security> doInBackground() throws Exception {
return FinanceFactory.getInstance().getAllSecurities();
}
@Override
protected void done() {
try {
lockUI.setLocked(true);
securitiesTableModel.setSecurities(get());
securitiesTableModel.fireTableDataChanged();
lockUI.setLocked(false);
} catch (InterruptedException ex) {
JXErrorPane.showDialog(new Exception(translations.getString("ERROR_FETCH_USERS_THREAD"), ex));
} catch (ExecutionException ex) {
JXErrorPane.showDialog(new Exception(translations.getString("ERROR_FETCH_USERS_EXECUTION_EXCEPTION"), ex));
}
}
};
worker.execute();
}
private class SecuritiesListActionPanel extends JPanel {
public SecuritiesListActionPanel() {
setLayout(new BorderLayout());
add(new JPanel() {
{
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
add(selectedLabel);
add(Box.createHorizontalGlue());
add(resumeSecurity);
add(suspendSecurity);
add(Box.createHorizontalStrut(10));
add(showSecurity);
add(hideSecurity);
}
}, BorderLayout.NORTH);
add(new JPanel() {
{
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
add(searchLabel);
add(searchField);
add(Box.createHorizontalStrut(300));
add(Box.createHorizontalGlue());
add(refreshButton);
add(saveButton);
}
}, BorderLayout.SOUTH);
}
}
public void filterByExchange(Exchange exchange) {
if (exchange == null) {
exchangeRowFilter = null;
} else {
indexRowFilter = null;
exchangeRowFilter = new ExchangeRowFilter(exchange);
}
updateFilters();
}
public void filterByIndex(Index index) {
if (index == null) {
indexRowFilter = null;
} else {
exchangeRowFilter = null;
indexRowFilter = new IndexRowFilter(index);
}
updateFilters();
}
private void updateFilters() {
List<RowFilter<TableModel, Integer>> filters = new ArrayList<RowFilter<TableModel, Integer>>();
String title = translations.getString("OVERVIEW");
if (exchangeRowFilter != null) {
filters.add(exchangeRowFilter);
title = translations.getString("SECURITIES_OF") + " '" + exchangeRowFilter.getExchange().getName() + "'";
}
if (indexRowFilter != null) {
filters.add(indexRowFilter);
title = translations.getString("SECURITIES_OF") + " '" + indexRowFilter.getIndex().getName() + "'";
}
if (stringRowFilter != null) {
filters.add(stringRowFilter);
title = title.concat(" " + translations.getString("FILTERED"));
}
if (!filters.isEmpty()) {
RowFilter<TableModel, Integer> comboFilter = RowFilter.andFilter(filters);
securitiesTable.setRowFilter(comboFilter);
} else {
securitiesTable.setRowFilter(null);
}
titleLabel.setText(title);
}
private class ExchangeRowFilter extends javax.swing.RowFilter<TableModel, Integer> {
private Exchange exchange;
public ExchangeRowFilter(Exchange exchange) {
this.exchange = exchange;
}
public Exchange getExchange() {
return exchange;
}
@Override
public boolean include(Entry<? extends TableModel, ? extends Integer> entry) {
SecuritiesTableModel model = (SecuritiesTableModel) entry.getModel();
Security sec = model.getSecurityAt(entry.getIdentifier());
return sec.getExchange().equals(exchange);
}
}
private class IndexRowFilter extends javax.swing.RowFilter<TableModel, Integer> {
private Collection<Security> securitiesFromIndex;
private Index index;
public Index getIndex() {
return index;
}
public IndexRowFilter(Index index) {
try {
this.index = index;
securitiesFromIndex = FinanceFactory.getInstance().getSecuritiesFromIndex(index);
} catch (StockPlayException ex) {
logger.error("Error while loading securities from index", ex);
}
}
@Override
public boolean include(Entry<? extends TableModel, ? extends Integer> entry) {
SecuritiesTableModel model = (SecuritiesTableModel) entry.getModel();
Security sec = model.getSecurityAt(entry.getIdentifier());
return securitiesFromIndex.contains(sec);
}
}
private class StringRowFilter extends javax.swing.RowFilter<TableModel, Integer> {
String str;
public StringRowFilter(String str) {
this.str = str;
}
@Override
public boolean include(Entry<? extends TableModel, ? extends Integer> entry) {
SecuritiesTableModel model = (SecuritiesTableModel) entry.getModel();
Security sec = model.getSecurityAt(entry.getIdentifier());
Pattern p = Pattern.compile(str + ".*", Pattern.CASE_INSENSITIVE);
if (p.matcher(sec.getName()).matches()) {
return true;
}
if (p.matcher(sec.getSymbol()).matches()) {
return true;
}
if (p.matcher(sec.getISIN()).matches()) {
return true;
}
return false;
}
}
}