package org.ripple.power.ui.btc;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;
import org.ripple.power.txns.btc.Address;
import org.ripple.power.txns.btc.BTCLoader;
import org.ripple.power.txns.btc.ECKey;
import org.ripple.power.txns.btc.FilterLoadMessage;
import org.ripple.power.txns.btc.Message;
import org.ripple.power.txns.btc.BlockStoreException;
import org.ripple.power.ui.UIRes;
import org.ripple.power.ui.table.AddressTable;
import org.ripple.power.ui.view.ButtonPane;
import org.ripple.power.ui.view.log.ErrorLog;
public class ReceiveAddressDialog extends JDialog implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private static final Class<?>[] columnClasses = {
String.class, String.class};
private static final String[] columnNames = {
"Name", "Address"};
private static final int[] columnTypes = {
AddressTable.NAME, AddressTable.ADDRESS};
private final AddressTableModel tableModel;
private final JTable table;
private final JScrollPane scrollPane;
public ReceiveAddressDialog(JDialog parent) {
super(parent, "Receive Addresses", Dialog.ModalityType.DOCUMENT_MODAL);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
tableModel = new AddressTableModel(columnNames, columnClasses);
table = new AddressTable(tableModel, columnTypes);
table.setRowSorter(new TableRowSorter<>(tableModel));
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollPane = new JScrollPane(table);
JPanel tablePane = new JPanel();
tablePane.setBackground(Color.WHITE);
tablePane.add(Box.createGlue());
tablePane.add(scrollPane);
tablePane.add(Box.createGlue());
JPanel buttonPane = new ButtonPane(this, 10, new String[] {"New", "new"},
new String[] {"Copy", "copy"},
new String[] {"Edit", "edit"},
new String[] {"Done", "done"});
buttonPane.setBackground(Color.white);
JPanel contentPane = new JPanel();
contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
contentPane.setOpaque(true);
contentPane.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
contentPane.setBackground(Color.WHITE);
contentPane.add(tablePane);
contentPane.add(buttonPane);
setContentPane(contentPane);
}
public static void showDialog(JDialog parent) {
try {
JDialog dialog = new ReceiveAddressDialog(parent);
dialog.pack();
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
} catch (Exception exc) {
ErrorLog.get().logException("Exception while displaying dialog", exc);
}
}
@Override
public void actionPerformed(ActionEvent ae) {
try {
String action = ae.getActionCommand();
if (action.equals("done")) {
setVisible(false);
dispose();
} else if (action.equals("new")) {
ECKey key = new ECKey();
editKey(key, -1);
} else {
int row = table.getSelectedRow();
if (row < 0) {
UIRes.showErrorMessage(this,"Error", "No entry selected");
} else {
row = table.convertRowIndexToModel(row);
switch (action) {
case "copy":
String address = (String)tableModel.getValueAt(row, 1);
StringSelection sel = new StringSelection(address);
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(sel, null);
break;
case "edit":
ECKey key = BTCLoader.keys.get(row);
editKey(key, row);
break;
}
}
}
} catch (BlockStoreException exc) {
ErrorLog.get().logException("Unable to update blockStore database", exc);
} catch (Exception exc) {
ErrorLog.get().logException("Exception while processing action event", exc);
}
}
private void editKey(ECKey key, int row) throws BlockStoreException {
Address addr = key.toAddress();
while (true) {
addr = AddressEditDialog.showDialog(this, addr, false);
if (addr == null)
break;
String label = addr.getLabel();
boolean valid = true;
synchronized(BTCLoader.lock) {
for (ECKey chkKey : BTCLoader.keys) {
if (chkKey == key)
continue;
if (chkKey.getLabel().compareToIgnoreCase(label) == 0) {
UIRes.showErrorMessage(this,"Error", "Duplicate name specified");
valid = false;
break;
}
}
if (valid) {
if (row >= 0)
BTCLoader.keys.remove(row);
boolean added = false;
for (int i=0; i<BTCLoader.keys.size(); i++) {
ECKey chkKey = BTCLoader.keys.get(i);
if (chkKey.getLabel().compareToIgnoreCase(label) > 0) {
key.setLabel(label);
BTCLoader.keys.add(i, key);
added = true;
break;
}
}
if (!added) {
key.setLabel(label);
BTCLoader.keys.add(key);
}
}
}
if (valid) {
if (row >= 0) {
BTCLoader.blockStore.setKeyLabel(key);
} else {
BTCLoader.blockStore.storeKey(key);
BTCLoader.bloomFilter.insert(key.getPubKey());
BTCLoader.bloomFilter.insert(key.getPubKeyHash());
Message filterMsg = FilterLoadMessage.buildFilterLoadMessage(null, BTCLoader.bloomFilter);
BTCLoader.networkHandler.broadcastMessage(filterMsg);
}
tableModel.fireTableDataChanged();
break;
}
}
}
private class AddressTableModel extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private String[] columnNames;
private Class<?>[] columnClasses;
public AddressTableModel(String[] columnNames, Class<?>[] columnClasses) {
super();
if (columnNames.length != columnClasses.length){
throw new IllegalArgumentException("Number of names not same as number of classes");
}
this.columnNames = columnNames;
this.columnClasses = columnClasses;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Class<?> getColumnClass(int column) {
return columnClasses[column];
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public int getRowCount() {
return BTCLoader.keys.size();
}
@Override
public Object getValueAt(int row, int column) {
if (row >= BTCLoader.keys.size()){
throw new IndexOutOfBoundsException("Table row "+row+" is not valid");
}
Object value;
ECKey key = BTCLoader.keys.get(row);
switch (column) {
case 0:
value = key.getLabel();
break;
case 1:
value = key.toAddress().toString();
break;
default:
throw new IndexOutOfBoundsException("Table column "+column+" is not valid");
}
return value;
}
}
}