package org.ripple.power.ui;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.ListSelectionModel;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import org.ripple.power.config.LSystem;
import org.ripple.power.helper.HelperDialog;
import org.ripple.power.helper.HelperWindow;
import org.ripple.power.i18n.LangConfig;
import org.ripple.power.txns.AccountFind;
import org.ripple.power.txns.AccountInfo;
import org.ripple.power.txns.AccountLine;
import org.ripple.power.txns.NameFind;
import org.ripple.power.txns.TransactionTx;
import org.ripple.power.txns.Updateable;
import org.ripple.power.ui.table.AddressTable;
import org.ripple.power.ui.view.ABaseDialog;
import org.ripple.power.ui.view.RPLabel;
import org.ripple.power.ui.view.RPTextBox;
import org.ripple.power.ui.view.RPToast;
import org.ripple.power.ui.view.WaitDialog;
import org.ripple.power.ui.view.RPToast.Style;
import org.ripple.power.utils.GraphicsUtils;
import org.ripple.power.utils.SwingUtils;
public class RPAccountInfoDialog extends ABaseDialog implements WindowListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private javax.swing.JSeparator _spOne;
private javax.swing.JSeparator _spTwo;
private RPCButton _loadButton;
private RPCButton _memoButton;
private RPCButton _hashButton;
private RPCButton _exitButton;
private RPLabel _addressLabel;
private RPLabel _assetsLabel;
private RPLabel _issuedLabel;
private RPLabel _booksLabel;
private RPTextBox _addressText;
private RPTextBox _addressNameText;
private AddressTable _tableOne;
private AddressTable _tableTwo;
private AddressTable _tableThree;
private javax.swing.JScrollPane _panelOne;
private javax.swing.JScrollPane _panelTwo;
private javax.swing.JScrollPane _panelThree;
private ArrayList<AccountLine> _accountLineItems = new ArrayList<AccountLine>();
private ArrayList<AccountLine> _accountLineItems2 = new ArrayList<AccountLine>();
private ArrayList<String> _accountLineItems3 = new ArrayList<String>();
private AccountInfo _accountinfo = new AccountInfo();
class AccountTableModel extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private String[] columnNames;
private Class<?>[] columnClasses;
public AccountTableModel(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 _accountLineItems.size();
}
@Override
public Object getValueAt(int row, int column) {
if (row > getRowCount()) {
throw new IndexOutOfBoundsException("Table row " + row
+ " is not valid");
}
Object value = null;
AccountLine item = (AccountLine) _accountLineItems.get(row);
switch (column) {
case 0:
value = item.getCurrency();
break;
case 1:
value = item.getIssuer();
break;
case 2:
value = item.getBalance();
break;
default:
throw new IndexOutOfBoundsException("Table column " + column
+ " is not valid");
}
return value;
}
public void update() {
fireTableDataChanged();
}
}
class AccountTableModel2 extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private String[] columnNames;
private Class<?>[] columnClasses;
public AccountTableModel2(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 _accountLineItems2.size();
}
@Override
public Object getValueAt(int row, int column) {
if (row > getRowCount()) {
throw new IndexOutOfBoundsException("Table row " + row
+ " is not valid");
}
if (_accountLineItems2.size() == 0) {
return null;
}
Object value = null;
AccountLine item = (AccountLine) _accountLineItems2.get(row);
switch (column) {
case 0:
value = item.getCurrency();
break;
case 1:
value = item.getIssuer();
break;
case 2:
value = item.getBalance();
break;
default:
throw new IndexOutOfBoundsException("Table column " + column
+ " is not valid");
}
return value;
}
public void update() {
fireTableDataChanged();
}
}
class AccountTableModel3 extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 1L;
private String[] columnNames;
private Class<?>[] columnClasses;
public AccountTableModel3(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 _accountLineItems3.size();
}
@Override
public Object getValueAt(int row, int column) {
if (row > getRowCount()) {
throw new IndexOutOfBoundsException("Table row " + row
+ " is not valid");
}
Object value = null;
String v = _accountLineItems3.get(row);
switch (column) {
case 0:
value = v;
break;
default:
throw new IndexOutOfBoundsException("Table column " + column
+ " is not valid");
}
return value;
}
public void update() {
fireTableDataChanged();
}
}
public static RPAccountInfoDialog showDialog(JFrame parent, String text,
String address) {
RPAccountInfoDialog dialog = new RPAccountInfoDialog(parent, text,
address);
dialog.pack();
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
return dialog;
}
public RPAccountInfoDialog(JFrame parent, String text, String address) {
super(parent, text, Dialog.ModalityType.DOCUMENT_MODAL);
setIconImage(UIRes.getIcon());
setResizable(false);
Dimension dim = new Dimension(668, 620);
setPreferredSize(dim);
setSize(dim);
initComponents(address);
}
private void initComponents(String address) {
addWindowListener(HelperWindow.get());
_addressLabel = new RPLabel();
_addressText = new RPTextBox();
_addressNameText = new RPTextBox();
_loadButton = new RPCButton();
_memoButton = new RPCButton();
_hashButton = new RPCButton();
_exitButton = new RPCButton();
_panelOne = new javax.swing.JScrollPane();
_panelTwo = new javax.swing.JScrollPane();
_panelThree = new javax.swing.JScrollPane();
_spOne = new javax.swing.JSeparator();
_spTwo = new javax.swing.JSeparator();
_assetsLabel = new RPLabel();
_issuedLabel = new RPLabel();
_booksLabel = new RPLabel();
Font font = UIRes.getFont();
_loadButton.setFont(font);
_exitButton.setFont(font);
Class<?>[] columnClasses = { String.class, String.class, String.class };
String[] columnNames = { UIMessage.currency, UIMessage.gateway,
UIMessage.amount };
int[] columnTypes = { AddressTable.ICON, AddressTable.ADDRESS,
AddressTable.AMOUNT };
final AccountTableModel tableModel = new AccountTableModel(columnNames,
columnClasses);
_tableOne = new AddressTable(tableModel, columnTypes);
_tableOne.setFont(UIRes.getFont());
_tableOne.setRowSorter(new TableRowSorter<TableModel>(tableModel));
_tableOne.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_panelOne.setViewportView(_tableOne);
getContentPane().add(_panelOne);
_panelOne.setBounds(10, 90, 640, 120);
final AccountTableModel2 tableModel2 = new AccountTableModel2(
columnNames, columnClasses);
_tableTwo = new AddressTable(tableModel2, columnTypes);
_tableTwo.setFont(UIRes.getFont());
_tableTwo.setRowSorter(new TableRowSorter<TableModel>(tableModel));
_tableTwo.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_panelTwo.setViewportView(_tableTwo);
getContentPane().add(_panelTwo);
_panelTwo.setBounds(10, 250, 640, 100);
getContentPane().add(_spTwo);
_spTwo.setBounds(0, 540, 670, 10);
_booksLabel.setFont(UIRes.getFont()); // NOI18N
_booksLabel.setText(LangConfig.get(this, "books", "Books"));
getContentPane().add(_booksLabel);
_booksLabel.setBounds(20, 360, 90, 20);
Class<?>[] columnClasses1 = { String.class };
String[] columnNames1 = { LangConfig.get(this, "tx",
"Transaction Records") };
int[] columnTypes1 = { AddressTable.INFO };
final AccountTableModel3 tableModel3 = new AccountTableModel3(
columnNames1, columnClasses1);
_tableThree = new AddressTable(tableModel3, columnTypes1);
_tableThree.setFont(UIRes.getFont());
_tableThree.setRowSorter(new TableRowSorter<TableModel>(tableModel3));
_tableThree.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
_tableThree.addMouseListener(new infoMouseListener());
addMouseListener(new infoMouseListener());
_panelThree.setViewportView(_tableThree);
getContentPane().add(_panelThree);
_panelThree.setBounds(10, 390, 640, 130);
getContentPane().setLayout(null);
_addressLabel.setText(LangConfig.get(this, "address", "Address"));
_addressLabel.setFont(new Font(LangConfig.getFontName(), 1, 14));
getContentPane().add(_addressLabel);
_addressLabel.setBounds(20, 25, 80, 15);
getContentPane().add(_addressText);
_addressText.setBounds(95, 22, 300, 21);
getContentPane().add(_addressNameText);
_addressNameText.setBounds(405, 22, 100, 21);
_addressNameText.setEditable(false);
_addressNameText.setFont(GraphicsUtils.getFont(Font.SANS_SERIF, 0, 12));
address = address.trim();
if (address.length() > 0) {
_addressText.setText(address);
_accountinfo = new AccountInfo();
try {
call(_accountinfo, tableModel, tableModel2, tableModel3);
} catch (Exception ex) {
_accountinfo = new AccountInfo();
}
} else {
_addressText.setText("");
_addressNameText.setText("Unkown");
}
_loadButton.setText(LangConfig.get(this, "load", "Load"));
_loadButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
_accountinfo = new AccountInfo();
try {
call(_accountinfo, tableModel, tableModel2, tableModel3);
} catch (Exception ex) {
_accountinfo = new AccountInfo();
}
}
});
getContentPane().add(_loadButton);
_loadButton.setBounds(513, 21, 125, 23);
_memoButton.setText("Memo Data");
_memoButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
String address = _addressText.getText().trim();
if (address.startsWith("~")) {
try {
address = NameFind.getAddress(address);
} catch (Exception ex) {
RPToast.makeText(RPAccountInfoDialog.this,
UIMessage.errAddress, Style.ERROR).display();
return;
}
}
if (!AccountFind.isRippleAddress(address)) {
RPToast.makeText(RPAccountInfoDialog.this,
UIMessage.errAddress, Style.ERROR).display();
return;
}
RPRippledMemoDialog.showDialog(
LangConfig.get(this, "send_memo", "Memo Send/Receive"),
LSystem.applicationMain, address, null);
}
});
getContentPane().add(_memoButton);
_memoButton.setBounds(11, 555, 165, 30);
_hashButton.setText("Hash Data");
_hashButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int size = _tableThree.getSelectedRow();
if (_accountinfo.transactions.size() > 0 && size > -1) {
UIMessage.infoMessage(RPAccountInfoDialog.this, "No:"
+ size);
TransactionTx tx = _accountinfo.getTxs("Payment").get(size);
RPHashInfoDialog.showDialog(RPAccountInfoDialog.this, tx);
} else {
RPHashInfoDialog.showDialog(RPAccountInfoDialog.this);
}
}
});
getContentPane().add(_hashButton);
_hashButton.setBounds(191, 555, 165, 30);
_exitButton.setText(LangConfig.get(this, "exit", "Exit"));
_exitButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
SwingUtils.close(RPAccountInfoDialog.this);
}
});
getContentPane().add(_exitButton);
_exitButton.setBounds(520, 555, 128, 30);
getContentPane().add(_spOne);
_spOne.setBounds(0, 60, 670, 10);
_assetsLabel.setFont(UIRes.getFont());
_assetsLabel.setText(LangConfig.get(this, "assets", "Assets"));
getContentPane().add(_assetsLabel);
_assetsLabel.setBounds(20, 65, 90, 20);
_issuedLabel.setFont(UIRes.getFont()); // NOI18N
_issuedLabel.setText(LangConfig.get(this, "issued", "Currency issued"));
getContentPane().add(_issuedLabel);
_issuedLabel.setBounds(20, 220, 190, 20);
getContentPane().setBackground(UIConfig.dialogbackground);
final String ddata = LangConfig.get(this, "ddata", "Detailed data");
UIRes.addPopMenu(_popMenu, ddata, new Updateable() {
@Override
public void action(Object o) {
int size = _tableThree.getSelectedRow();
if (_accountinfo.transactions.size() > 0 && size > -1) {
UIMessage.infoMessage(RPAccountInfoDialog.this, "No:"
+ size);
TransactionTx tx = _accountinfo.getTxs("Payment").get(size);
RPHashInfoDialog.showDialog(RPAccountInfoDialog.this, tx);
} else {
RPHashInfoDialog.showDialog(RPAccountInfoDialog.this);
}
}
});
pack();
HelperDialog.setSystemHelperMessage("View the Ripple address detail data [ if your using a Ripple Labs public node , please update node to the s2.ripple.com view all history , s1.ripple.com only save one month's transactions ] . ");
}
private JPopupMenu _popMenu = new JPopupMenu();
private class infoMouseListener extends MouseAdapter {
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger()) {
_popMenu.show((Component) e.getSource(), e.getX(), e.getY());
}
}
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
_popMenu.show((Component) e.getSource(), e.getX(), e.getY());
}
}
}
private final static ArrayList<Store> _storage = new ArrayList<Store>();
private static class Store {
public AccountInfo info;
public String name;
public long date = 0;
public Store(String n, AccountInfo i) {
this.name = n;
this.info = i;
this.date = System.currentTimeMillis();
}
}
private static AccountInfo reset(String name) {
for (Store s : _storage) {
if (s.name.equals(name)
&& (System.currentTimeMillis() - s.date) <= (LSystem.MINUTE / 2)) {
return s.info;
} else if (s.name.equals(name)) {
_storage.remove(s);
return null;
}
}
return null;
}
private static void addStorage(Store s) {
_storage.add(s);
if (_storage.size() > 100) {
_storage.remove(0);
}
}
private static void addList(ArrayList<String> list, TransactionTx tx,
int count) {
if ("Payment".equals(tx.clazz)) {
if (tx.counterparty != null) {
list.add("No:" + count + " in " + tx.date + "<br>"
+ "<font size=4 color=red>" + tx.mode + "</font>" + " "
+ "<font size=4 color=blue>" + tx.counterparty
+ "</font>" + "<br>" + tx.currency.toGatewayString()
+ "<br>" + "Fee:" + tx.fee);
} else {
list.add("No:" + count + " in " + tx.date + "<br>"
+ "<font size=4 color=red>" + tx.mode + "</font>" + " "
+ tx.currency.toGatewayString() + "<br>" + "Fee:"
+ tx.fee);
}
count++;
}
}
private ArrayList<WaitDialog> _waitDialogs = new ArrayList<WaitDialog>(10);
public void call(final AccountInfo info,
final AccountTableModel tableModel,
final AccountTableModel2 tableModel2,
final AccountTableModel3 tableModel3) {
LSystem.invokeLater(new Runnable() {
@Override
public void run() {
String address = _addressText.getText().trim();
AccountInfo info_tmp = reset(address);
if (info_tmp != null) {
info.copy(info_tmp);
if (info.balance != null) {
synchronized (_accountLineItems) {
_accountLineItems.clear();
_accountLineItems
.add(new AccountLine("RippleLabels",
LSystem.nativeCurrency.toUpperCase(),
info.balance));
tableModel.update();
}
}
_addressNameText.setText(info.address);
if (info.lines.size() > 0) {
synchronized (_accountLineItems) {
_accountLineItems.clear();
_accountLineItems
.add(new AccountLine("RippleLabels",
LSystem.nativeCurrency.toUpperCase(),
info.balance));
_accountLineItems.addAll(info.lines);
}
tableModel.update();
}
if (info.debt.size() > 0) {
synchronized (_accountLineItems2) {
_accountLineItems2.clear();
for (String cur : info.debt.keySet()) {
AccountLine line = new AccountLine(address, cur,
String.valueOf(info.debt.get(cur)));
_accountLineItems2.add(line);
}
}
tableModel2.update();
}
if (info.transactions.size() > 0) {
synchronized (_accountLineItems3) {
_accountLineItems3.clear();
int count = 0;
for (TransactionTx tx : info.transactions) {
if ("Payment".equals(tx.clazz)) {
addList(_accountLineItems3, tx, count++);
}
}
}
tableModel3.update();
}
return;
}
Updateable updateAll = new Updateable() {
@Override
public void action(Object o) {
String addressTmp = _addressText.getText().trim();
// revalidate();
// repaint();
final WaitDialog waitDialog = WaitDialog
.showDialog(RPAccountInfoDialog.this);
_waitDialogs.add(waitDialog);
// revalidate();
// repaint();
if (addressTmp.startsWith("~")) {
try {
addressTmp = NameFind.getAddress(addressTmp);
} catch (Exception ex) {
RPToast.makeText(RPAccountInfoDialog.this,
UIMessage.errAddress, Style.ERROR).display();
return;
}
}
if (!AccountFind.isRippleAddress(addressTmp)) {
RPToast.makeText(RPAccountInfoDialog.this,
UIMessage.errAddress, Style.ERROR).display();
return;
}
final String address = addressTmp;
AccountFind find = new AccountFind();
// revalidate();
// repaint();
Updateable update_info = new Updateable() {
@Override
public void action(Object res) {
if (info.count < 2) {
if (info.balance != null) {
synchronized (_accountLineItems) {
_accountLineItems.clear();
_accountLineItems.add(new AccountLine(
"RippleLabels",
LSystem.nativeCurrency
.toUpperCase(),
info.balance));
tableModel.update();
}
}
}
String name = null;
try {
name = NameFind.getName(address);
} catch (Exception ex) {
name = "Unkown";
}
if (name == null || name.equalsIgnoreCase(address)) {
name = "Unkown";
}
_addressNameText.setText(name);
// RPAccountInfoDialog.this.revalidate();
// RPAccountInfoDialog.this.repaint();
}
};
Updateable update_line = new Updateable() {
@Override
public void action(Object res) {
if (info.lines.size() > 0) {
synchronized (_accountLineItems) {
_accountLineItems.clear();
_accountLineItems.add(new AccountLine(
"RippleLabels", LSystem.nativeCurrency
.toUpperCase(), info.balance));
_accountLineItems.addAll(info.lines);
}
tableModel.update();
}
if (info.debt.size() > 0) {
synchronized (_accountLineItems2) {
_accountLineItems2.clear();
for (String cur : info.debt.keySet()) {
AccountLine line = new AccountLine(address,
cur, String.valueOf(info.debt
.get(cur)));
_accountLineItems2.add(line);
}
}
tableModel2.update();
}
// RPAccountInfoDialog.this.revalidate();
// RPAccountInfoDialog.this.repaint();
}
};
Updateable update_tx = new Updateable() {
@Override
public void action(Object res) {
if (info.transactions.size() > 0) {
synchronized (_accountLineItems3) {
_accountLineItems3.clear();
int count = 0;
for (TransactionTx tx : info.transactions) {
if ("Payment".equals(tx.clazz)) {
addList(_accountLineItems3, tx, count++);
}
}
}
tableModel3.update();
addStorage(new Store(address,
new AccountInfo().copy(info)));
}
waitDialog.closeDialog();
/*
* RPAccountInfoDialog.this.revalidate();
* RPAccountInfoDialog.this.repaint(); if
* (LSystem.applicationMain != null) {
* LSystem.applicationMain.revalidate();
* LSystem.applicationMain.repaint(); }
*/
}
};
find.processInfo(address, info, update_info);
find.processLines(address, info, update_line);
find.processTx(address, info, update_tx);
// revalidate();
// repaint();
}
};
LSystem.postThread(updateAll);
}
});
}
public AccountInfo getAccountinfo() {
return _accountinfo;
}
@Override
public void windowActivated(WindowEvent e) {
}
@Override
public void windowClosed(WindowEvent e) {
if (_waitDialogs != null) {
for (WaitDialog wait : _waitDialogs) {
if (wait != null) {
wait.closeDialog();
}
}
}
}
@Override
public void windowClosing(WindowEvent e) {
}
@Override
public void windowDeactivated(WindowEvent e) {
}
@Override
public void windowDeiconified(WindowEvent e) {
}
@Override
public void windowIconified(WindowEvent e) {
}
@Override
public void windowOpened(WindowEvent e) {
}
}