Blockchain browser rebuilded.
This commit is contained in:
parent
f0ddccd490
commit
e933908dc2
|
@ -1,40 +1,110 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.text.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.*;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 15/05/14 12:36
|
||||
*
|
||||
* @author: Adrian Benko
|
||||
* Created on: 27/08/14 18:22
|
||||
*/
|
||||
public class BlockChainTable extends JFrame {
|
||||
public class BlockChainTable extends JFrame implements ActionListener {
|
||||
|
||||
final static int BLOCK_CHECK_INTERVAL = 1000;
|
||||
final static String FONT_NAME = "Courier New";
|
||||
final static int FONT_SIZE_TITLE = 20;
|
||||
final static int FONT_SIZE = 13;
|
||||
|
||||
final static Font boldTitle = new Font(FONT_NAME, Font.BOLD, FONT_SIZE_TITLE);
|
||||
final static Font bold = new Font(FONT_NAME, Font.BOLD, FONT_SIZE);
|
||||
final static Font plain = new Font(FONT_NAME, Font.PLAIN, FONT_SIZE);
|
||||
final static Color HILIT_COLOR = Color.LIGHT_GRAY;
|
||||
|
||||
class MyDocumentFilter extends DocumentFilter {
|
||||
@Override
|
||||
public void insertString(FilterBypass fb, int off
|
||||
, String str, AttributeSet attr)
|
||||
throws BadLocationException {
|
||||
// remove non-digits
|
||||
fb.insertString(off, str.replaceAll("\\D++", ""), attr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replace(FilterBypass fb, int off
|
||||
, int len, String str, AttributeSet attr)
|
||||
throws BadLocationException {
|
||||
// remove non-digits
|
||||
fb.replace(off, len, str.replaceAll("\\D++", ""), attr);
|
||||
}
|
||||
}
|
||||
|
||||
private volatile boolean running;
|
||||
private TransactionData transactionDataWindow = null;
|
||||
|
||||
private JPanel topPanel;
|
||||
private JTable table;
|
||||
private JScrollPane scrollPane;
|
||||
private JPanel titlePanel;
|
||||
private JPanel blockPanel;
|
||||
private JPanel transactionsPanel;
|
||||
private JScrollPane scrollPane;
|
||||
|
||||
private int lastFindIndex = 0;
|
||||
JTextField blockNumberText;
|
||||
JButton firstBlock;
|
||||
JButton prevBlock;
|
||||
JButton nextBlock;
|
||||
JButton lastBlock;
|
||||
JLabel blocksCount;
|
||||
JTextField findText;
|
||||
JButton findPrev;
|
||||
JButton findNext;
|
||||
|
||||
JTextField blockN;
|
||||
JTextField minGasPrice;
|
||||
JTextField gasLimit;
|
||||
JTextField gasUsed;
|
||||
JTextField timestamp;
|
||||
JTextField difficulty;
|
||||
JTextField hash;
|
||||
JTextField parentHash;
|
||||
JTextField uncleHash;
|
||||
JTextField stateRoot;
|
||||
JTextField trieRoot;
|
||||
JTextField coinbase;
|
||||
JTextField nonce;
|
||||
JTextField extraData;
|
||||
|
||||
Thread t;
|
||||
|
||||
private int lastFindIndex = -1;
|
||||
private String textToFind = "";
|
||||
private java.util.List<Long> foundBlocks;
|
||||
final Highlighter.HighlightPainter painter;
|
||||
|
||||
ToolBar toolBar;
|
||||
|
||||
public BlockChainTable(ToolBar toolBar) {
|
||||
|
||||
this.toolBar = toolBar;
|
||||
addCloseAction();
|
||||
|
||||
final BlockChainTable blockchainTable = this;
|
||||
foundBlocks = new ArrayList<Long>();
|
||||
painter = new DefaultHighlighter.DefaultHighlightPainter(HILIT_COLOR);
|
||||
|
||||
setTitle("Block Chain Table");
|
||||
setSize(700, 400);
|
||||
setLocation(315, 180);
|
||||
setSize(900, 400);
|
||||
setLocation(315, 270);
|
||||
setBackground(Color.gray);
|
||||
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
|
@ -42,100 +112,738 @@ public class BlockChainTable extends JFrame {
|
|||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
|
||||
|
||||
// Create a panel to hold all other components
|
||||
topPanel = new JPanel();
|
||||
topPanel.setLayout(new BorderLayout());
|
||||
getContentPane().add(topPanel);
|
||||
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.PAGE_AXIS));
|
||||
getContentPane().add(topPanel, BorderLayout.LINE_START);
|
||||
|
||||
// Create a new table getInstance()
|
||||
table = new JTable();
|
||||
table.setModel(new BlockTableModel());
|
||||
titlePanel = new JPanel(new FlowLayout());
|
||||
titlePanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
|
||||
createTitlePanel(this);
|
||||
|
||||
table.setFont(new Font("Courier New", Font.PLAIN, 13));
|
||||
table.setForeground(Color.GRAY);
|
||||
table.setTableHeader(null);
|
||||
blockPanel = new JPanel(new GridBagLayout());
|
||||
blockPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 160));
|
||||
createBlockPanel();
|
||||
|
||||
TableCellRenderer tcr = table.getDefaultRenderer(String.class);
|
||||
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) tcr;
|
||||
renderer.setHorizontalAlignment(SwingConstants.LEFT);
|
||||
renderer.setVerticalAlignment(SwingConstants.TOP);
|
||||
transactionsPanel = new JPanel(new GridBagLayout());
|
||||
transactionsPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 160));
|
||||
fillBlock(this);
|
||||
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
table.setCellSelectionEnabled(true);
|
||||
titlePanel.setAlignmentX(0);
|
||||
topPanel.add(titlePanel);
|
||||
blockPanel.setAlignmentX(0);
|
||||
topPanel.add(blockPanel);
|
||||
|
||||
table.setRowMargin(3);
|
||||
table.setRowHeight(420);
|
||||
JLabel transactionsLabel = new JLabel("Transactions ");
|
||||
transactionsLabel.setFont(bold);
|
||||
transactionsLabel.setAlignmentX(0);
|
||||
transactionsLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
|
||||
topPanel.add(transactionsLabel);
|
||||
|
||||
table.getColumnModel().getColumn(0).setCellRenderer(new TableCellLongTextRenderer());
|
||||
scrollPane = new JScrollPane(transactionsPanel);
|
||||
scrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||
scrollPane.setAlignmentX(0);
|
||||
topPanel.add(scrollPane);
|
||||
|
||||
table.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK), "Copy");
|
||||
table.getActionMap().put("Copy", new AbstractAction() {
|
||||
topPanel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK), "Copy");
|
||||
topPanel.getActionMap().put("Copy", new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
if (UIEthereumManager.ethereum.getBlockChain().getSize() - 1 < lastFindIndex) return;
|
||||
if (WorldManager.getInstance().getBlockchain().getSize() - 1 < lastFindIndex) return;
|
||||
|
||||
Block block = UIEthereumManager.ethereum.getBlockChain().getBlockByNumber(lastFindIndex);
|
||||
StringSelection stsel = new StringSelection(block.toString());
|
||||
Block block = WorldManager.getInstance().getBlockchain().getBlockByNumber(lastFindIndex);
|
||||
StringSelection selection = new StringSelection(block.toString());
|
||||
Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
system.setContents(stsel,stsel);
|
||||
system.setContents(selection, selection);
|
||||
}
|
||||
});
|
||||
|
||||
table.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F, KeyEvent.CTRL_DOWN_MASK), "Find");
|
||||
table.getActionMap().put("Find", new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
String toFind = JOptionPane.showInputDialog(blockchainTable, "Find:",
|
||||
"Find in BlockChain", JOptionPane.QUESTION_MESSAGE);
|
||||
|
||||
if (toFind.equals("")) {
|
||||
lastFindIndex = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = lastFindIndex + 1; i < UIEthereumManager.ethereum.getBlockChain().getSize(); ++i) {
|
||||
|
||||
if (UIEthereumManager.ethereum.getBlockChain().getSize() - 1 < i) return;
|
||||
Block block = UIEthereumManager.ethereum.getBlockChain().getBlockByNumber(i);
|
||||
boolean found = block.toString().toLowerCase().contains(toFind.toLowerCase());
|
||||
if (found) {
|
||||
// TODO: now we find the first occur
|
||||
// TODO: in the future I should keep
|
||||
// TODO: all of them and allow to jump over them
|
||||
table.scrollRectToVisible(table.getCellRect(i, 0, true));
|
||||
lastFindIndex = i;
|
||||
break;
|
||||
t = new Thread() {
|
||||
public void run() {
|
||||
running = true;
|
||||
while (running) {
|
||||
blocksCount.setText("" + WorldManager.getInstance().getBlockchain().getSize());
|
||||
try {
|
||||
sleep(BLOCK_CHECK_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
table.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
lastFindIndex = ((JTable) (e.getSource())).rowAtPoint(e.getPoint());
|
||||
super.mouseClicked(e);
|
||||
}
|
||||
});
|
||||
// Add the table to a scrolling pane
|
||||
scrollPane = new JScrollPane(table);
|
||||
topPanel.add(scrollPane, BorderLayout.CENTER);
|
||||
};
|
||||
t.start();
|
||||
}
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
toolBar.chainToggle.setSelected(false);
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
long blockNum = Long.parseLong(blockNumberText.getText());
|
||||
if ("firstBlock".equals(e.getActionCommand())) {
|
||||
blockNum = 0;
|
||||
} else if ("prevBlock".equals(e.getActionCommand())) {
|
||||
if (blockNum > 0) {
|
||||
blockNum--;
|
||||
}
|
||||
} else if ("nextBlock".equals(e.getActionCommand())) {
|
||||
if (blockNum < WorldManager.getInstance().getBlockchain().getSize() - 1) {
|
||||
blockNum++;
|
||||
}
|
||||
} else if ("lastBlock".equals(e.getActionCommand())) {
|
||||
blockNum = WorldManager.getInstance().getBlockchain().getSize() - 1;
|
||||
} else if ("findPrev".equals(e.getActionCommand())) {
|
||||
if (findText.getText().length() > 0) {
|
||||
if (textToFind.equals(findText.getText())) {
|
||||
if (lastFindIndex > 0) {
|
||||
blockNum = foundBlocks.get(lastFindIndex - 1);
|
||||
lastFindIndex--;
|
||||
} else {
|
||||
blockNum = findBlock(textToFind, blockNum, false);
|
||||
}
|
||||
} else {
|
||||
textToFind = findText.getText();
|
||||
lastFindIndex = -1;
|
||||
foundBlocks.clear();
|
||||
blockNum = findBlock(textToFind, blockNum, false);
|
||||
}
|
||||
}
|
||||
} else if ("findNext".equals(e.getActionCommand())) {
|
||||
if (findText.getText().length() > 0) {
|
||||
if (textToFind.equals(findText.getText())) {
|
||||
if (lastFindIndex > -1 && foundBlocks.size() > lastFindIndex + 1) {
|
||||
blockNum = foundBlocks.get(lastFindIndex + 1);
|
||||
lastFindIndex++;
|
||||
} else {
|
||||
blockNum = findBlock(textToFind, blockNum, true);
|
||||
}
|
||||
} else {
|
||||
textToFind = findText.getText();
|
||||
lastFindIndex = -1;
|
||||
foundBlocks.clear();
|
||||
blockNum = findBlock(textToFind, blockNum, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
blockNumberText.setText("" + blockNum);
|
||||
fillBlock(this);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
private long findBlock(String textToFind, long blockNum, boolean forward) {
|
||||
if (forward) {
|
||||
for (long i = blockNum + 1; i < WorldManager.getInstance().getBlockchain().getSize(); i++) {
|
||||
Block block = WorldManager.getInstance().getBlockchain().getBlockByNumber(i);
|
||||
if (block.toString().toLowerCase().contains(textToFind.toLowerCase())) {
|
||||
foundBlocks.add(i);
|
||||
lastFindIndex = foundBlocks.size() - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (long i = blockNum - 1; i >= 0; i--) {
|
||||
Block block = WorldManager.getInstance().getBlockchain().getBlockByNumber(i);
|
||||
if (block.toString().toLowerCase().contains(textToFind.toLowerCase())) {
|
||||
foundBlocks.add(0, i);
|
||||
lastFindIndex = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundBlocks.get(lastFindIndex);
|
||||
}
|
||||
|
||||
public void terminate() {
|
||||
running = false;
|
||||
}
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
toolBar.chainToggle.setSelected(false);
|
||||
if (transactionDataWindow != null) {
|
||||
transactionDataWindow.setVisible(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
BlockChainTable mainFrame = new BlockChainTable(null);
|
||||
mainFrame.setVisible(true);
|
||||
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
|
||||
private void createTitlePanel(final BlockChainTable blockchainTable) {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
JLabel blockNumberLabel = new JLabel("Block #");
|
||||
blockNumberLabel.setFont(boldTitle);
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
titlePanel.add(blockNumberLabel, c);
|
||||
|
||||
blockNumberText = new JTextField("0", 7);
|
||||
((AbstractDocument) blockNumberText.getDocument()).setDocumentFilter(
|
||||
new MyDocumentFilter());
|
||||
// Listen for changes in the text
|
||||
blockNumberText.getDocument().addDocumentListener(new DocumentListener() {
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
fillBlock(blockchainTable);
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
fillBlock(blockchainTable);
|
||||
}
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
fillBlock(blockchainTable);
|
||||
}
|
||||
});
|
||||
|
||||
blockNumberText.setFont(boldTitle);
|
||||
c.gridx = 1;
|
||||
c.gridy = 0;
|
||||
c.weightx = 1.0;
|
||||
c.insets = new Insets(0, 0, 0, 10);
|
||||
titlePanel.add(blockNumberText, c);
|
||||
|
||||
firstBlock = new JButton("|<");
|
||||
firstBlock.setFont(plain);
|
||||
firstBlock.setActionCommand("firstBlock");
|
||||
firstBlock.addActionListener(this);
|
||||
c.gridx = 2;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
titlePanel.add(firstBlock, c);
|
||||
|
||||
prevBlock = new JButton("<");
|
||||
prevBlock.setFont(plain);
|
||||
prevBlock.setActionCommand("prevBlock");
|
||||
prevBlock.addActionListener(this);
|
||||
c.gridx = 3;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
titlePanel.add(prevBlock, c);
|
||||
|
||||
nextBlock = new JButton(">");
|
||||
nextBlock.setFont(plain);
|
||||
nextBlock.setActionCommand("nextBlock");
|
||||
nextBlock.addActionListener(this);
|
||||
c.gridx = 4;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
titlePanel.add(nextBlock, c);
|
||||
|
||||
lastBlock = new JButton(">|");
|
||||
lastBlock.setFont(plain);
|
||||
lastBlock.setActionCommand("lastBlock");
|
||||
lastBlock.addActionListener(this);
|
||||
c.gridx = 5;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
titlePanel.add(lastBlock, c);
|
||||
|
||||
JLabel blocksCountLabel = new JLabel("Total blocks: ");
|
||||
blocksCountLabel.setFont(plain);
|
||||
c.gridx = 6;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
titlePanel.add(blocksCountLabel, c);
|
||||
|
||||
blocksCount = new JLabel();
|
||||
blocksCount.setFont(plain);
|
||||
c.gridx = 7;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
titlePanel.add(blocksCount, c);
|
||||
|
||||
JLabel findLabel = new JLabel("Find ");
|
||||
findLabel.setFont(plain);
|
||||
c.gridx = 8;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
titlePanel.add(findLabel, c);
|
||||
|
||||
findText = new JTextField(12);
|
||||
findText.setFont(plain);
|
||||
c.gridx = 9;
|
||||
c.gridy = 0;
|
||||
c.weightx = 3.0;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
titlePanel.add(findText, c);
|
||||
|
||||
findPrev = new JButton("<");
|
||||
findPrev.setFont(plain);
|
||||
findPrev.setActionCommand("findPrev");
|
||||
findPrev.addActionListener(this);
|
||||
c.gridx = 10;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
titlePanel.add(findPrev, c);
|
||||
|
||||
findNext = new JButton(">");
|
||||
findNext.setFont(plain);
|
||||
findNext.setActionCommand("findNext");
|
||||
findNext.addActionListener(this);
|
||||
c.gridx = 11;
|
||||
c.gridy = 0;
|
||||
c.weightx = 0.0;
|
||||
c.insets = new Insets(0, 0, 0, 10);
|
||||
titlePanel.add(findNext, c);
|
||||
}
|
||||
|
||||
private void createBlockPanel() {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
JLabel summaryLabel = new JLabel("Summary ");
|
||||
summaryLabel.setFont(bold);
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
blockPanel.add(summaryLabel, c);
|
||||
|
||||
JLabel blocknLabel = new JLabel("Block#");
|
||||
blocknLabel.setFont(plain);
|
||||
c.weightx = 1.0;
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
blockPanel.add(blocknLabel, c);
|
||||
|
||||
blockN = new JTextField();
|
||||
blockN.setEditable(false);
|
||||
blockN.setBorder(null);
|
||||
blockN.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 2;
|
||||
blockPanel.add(blockN, c);
|
||||
|
||||
JLabel minGasPriceLabel = new JLabel("Min gas price");
|
||||
minGasPriceLabel.setFont(plain);
|
||||
c.weightx = 1.0;
|
||||
c.gridx = 0;
|
||||
c.gridy = 3;
|
||||
blockPanel.add(minGasPriceLabel, c);
|
||||
|
||||
minGasPrice = new JTextField();
|
||||
minGasPrice.setEditable(false);
|
||||
minGasPrice.setBorder(null);
|
||||
minGasPrice.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 3;
|
||||
blockPanel.add(minGasPrice, c);
|
||||
|
||||
JLabel gasLimitLabel = new JLabel("Gas limit");
|
||||
gasLimitLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 4;
|
||||
blockPanel.add(gasLimitLabel, c);
|
||||
|
||||
gasLimit = new JTextField();
|
||||
gasLimit.setEditable(false);
|
||||
gasLimit.setBorder(null);
|
||||
gasLimit.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 4;
|
||||
blockPanel.add(gasLimit, c);
|
||||
|
||||
JLabel gasUsedLabel = new JLabel("Gas used");
|
||||
gasUsedLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 5;
|
||||
blockPanel.add(gasUsedLabel, c);
|
||||
|
||||
gasUsed = new JTextField();
|
||||
gasUsed.setEditable(false);
|
||||
gasUsed.setBorder(null);
|
||||
gasUsed.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 5;
|
||||
blockPanel.add(gasUsed, c);
|
||||
|
||||
JLabel timestampLabel = new JLabel("Timestamp");
|
||||
timestampLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 6;
|
||||
blockPanel.add(timestampLabel, c);
|
||||
|
||||
timestamp = new JTextField();
|
||||
timestamp.setEditable(false);
|
||||
timestamp.setBorder(null);
|
||||
timestamp.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 6;
|
||||
blockPanel.add(timestamp, c);
|
||||
|
||||
JLabel difficultyLabel = new JLabel("Difficulty");
|
||||
difficultyLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 7;
|
||||
blockPanel.add(difficultyLabel, c);
|
||||
|
||||
difficulty = new JTextField();
|
||||
difficulty.setEditable(false);
|
||||
difficulty.setBorder(null);
|
||||
difficulty.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 7;
|
||||
blockPanel.add(difficulty, c);
|
||||
|
||||
JLabel extraDataLabel = new JLabel("Extra data");
|
||||
extraDataLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 9;
|
||||
blockPanel.add(extraDataLabel, c);
|
||||
|
||||
extraData = new JTextField();
|
||||
extraData.setEditable(false);
|
||||
extraData.setBorder(null);
|
||||
extraData.setFont(plain);
|
||||
c.ipady = 1;
|
||||
c.ipadx = 1;
|
||||
c.gridx = 1;
|
||||
c.gridy = 9;
|
||||
c.gridwidth = GridBagConstraints.REMAINDER;
|
||||
blockPanel.add(extraData, c);
|
||||
|
||||
JLabel hashesLabel = new JLabel("Hashes ");
|
||||
hashesLabel.setFont(bold);
|
||||
c.gridx = 3;
|
||||
c.gridy = 1;
|
||||
c.gridwidth = 1;
|
||||
blockPanel.add(hashesLabel, c);
|
||||
|
||||
JLabel hashLabel = new JLabel("Hash");
|
||||
hashLabel.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 2;
|
||||
blockPanel.add(hashLabel, c);
|
||||
|
||||
hash = new JTextField();
|
||||
hash.setEditable(false);
|
||||
hash.setBorder(null);
|
||||
hash.setFont(plain);
|
||||
c.weightx = 3.0;
|
||||
c.gridx = 4;
|
||||
c.gridy = 2;
|
||||
blockPanel.add(hash, c);
|
||||
|
||||
JLabel parentHashLabel = new JLabel("Parent hash");
|
||||
parentHashLabel.setFont(plain);
|
||||
c.weightx = 1.0;
|
||||
c.gridx = 3;
|
||||
c.gridy = 3;
|
||||
blockPanel.add(parentHashLabel, c);
|
||||
|
||||
parentHash = new JTextField();
|
||||
parentHash.setEditable(false);
|
||||
parentHash.setBorder(null);
|
||||
parentHash.setFont(plain);
|
||||
c.gridx = 4;
|
||||
c.gridy = 3;
|
||||
blockPanel.add(parentHash, c);
|
||||
|
||||
JLabel uncleHashLabel = new JLabel("Uncle hash");
|
||||
uncleHashLabel.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 4;
|
||||
blockPanel.add(uncleHashLabel, c);
|
||||
|
||||
uncleHash = new JTextField();
|
||||
uncleHash.setEditable(false);
|
||||
uncleHash.setBorder(null);
|
||||
uncleHash.setFont(plain);
|
||||
c.gridx = 4;
|
||||
c.gridy = 4;
|
||||
blockPanel.add(uncleHash, c);
|
||||
|
||||
JLabel stateRootLabel = new JLabel("State root");
|
||||
stateRootLabel.setFont(plain);
|
||||
c.weightx = 1.0;
|
||||
c.gridx = 3;
|
||||
c.gridy = 5;
|
||||
blockPanel.add(stateRootLabel, c);
|
||||
|
||||
stateRoot = new JTextField();
|
||||
stateRoot.setEditable(false);
|
||||
stateRoot.setBorder(null);
|
||||
stateRoot.setFont(plain);
|
||||
c.gridx = 4;
|
||||
c.gridy = 5;
|
||||
blockPanel.add(stateRoot, c);
|
||||
|
||||
JLabel trieRootLabel = new JLabel("Trie root");
|
||||
trieRootLabel.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 6;
|
||||
blockPanel.add(trieRootLabel, c);
|
||||
|
||||
trieRoot = new JTextField();
|
||||
trieRoot.setEditable(false);
|
||||
trieRoot.setBorder(null);
|
||||
trieRoot.setFont(plain);
|
||||
c.gridx = 4;
|
||||
c.gridy = 6;
|
||||
blockPanel.add(trieRoot, c);
|
||||
|
||||
JLabel coinbaseLabel = new JLabel("Coinbase");
|
||||
coinbaseLabel.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 7;
|
||||
blockPanel.add(coinbaseLabel, c);
|
||||
|
||||
coinbase = new JTextField();
|
||||
coinbase.setEditable(false);
|
||||
coinbase.setBorder(null);
|
||||
coinbase.setFont(plain);
|
||||
c.gridx = 4;
|
||||
c.gridy = 7;
|
||||
blockPanel.add(coinbase, c);
|
||||
|
||||
JLabel nonceLabel = new JLabel("Nonce");
|
||||
nonceLabel.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 8;
|
||||
blockPanel.add(nonceLabel, c);
|
||||
|
||||
nonce = new JTextField();
|
||||
nonce.setEditable(false);
|
||||
nonce.setBorder(null);
|
||||
nonce.setFont(plain);
|
||||
c.gridx = 4;
|
||||
c.gridy = 8;
|
||||
blockPanel.add(nonce, c);
|
||||
}
|
||||
|
||||
private void fillBlock(final BlockChainTable blockchainTable) {
|
||||
if (blockNumberText.getText().length() == 0) return;
|
||||
|
||||
long blockNum = Long.parseLong(blockNumberText.getText());
|
||||
if (blockNum > WorldManager.getInstance().getBlockchain().getSize() - 1) {
|
||||
blockNum = WorldManager.getInstance().getBlockchain().getSize() - 1;
|
||||
}
|
||||
Block block = WorldManager.getInstance().getBlockchain().getBlockByNumber(blockNum);
|
||||
blockN.setText("" + block.getNumber());
|
||||
highlightText(blockN);
|
||||
minGasPrice.setText("" + block.getMinGasPrice());
|
||||
highlightText(minGasPrice);
|
||||
gasLimit.setText("" + block.getGasLimit());
|
||||
highlightText(gasLimit);
|
||||
gasUsed.setText("" + block.getGasUsed());
|
||||
highlightText(gasUsed);
|
||||
timestamp.setText(Utils.longToDateTime(block.getTimestamp()));
|
||||
highlightText(timestamp);
|
||||
difficulty.setText(ByteUtil.toHexString(block.getDifficulty()));
|
||||
highlightText(difficulty);
|
||||
|
||||
hash.setText(ByteUtil.toHexString(block.getHash()));
|
||||
highlightText(hash);
|
||||
parentHash.setText(ByteUtil.toHexString(block.getParentHash()));
|
||||
highlightText(parentHash);
|
||||
uncleHash.setText(ByteUtil.toHexString(block.getUnclesHash()));
|
||||
highlightText(uncleHash);
|
||||
stateRoot.setText(ByteUtil.toHexString(block.getStateRoot()));
|
||||
highlightText(stateRoot);
|
||||
trieRoot.setText(ByteUtil.toHexString(block.getTxTrieRoot()));
|
||||
highlightText(trieRoot);
|
||||
coinbase.setText(ByteUtil.toHexString(block.getCoinbase()));
|
||||
highlightText(coinbase);
|
||||
nonce.setText(ByteUtil.toHexString(block.getNonce()));
|
||||
highlightText(nonce);
|
||||
if (block.getExtraData() != null) {
|
||||
extraData.setText(ByteUtil.toHexString(block.getExtraData()));
|
||||
highlightText(extraData);
|
||||
}
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
transactionsPanel.removeAll();
|
||||
|
||||
int row = 1;
|
||||
for (Transaction transaction : block.getTransactionsList()) {
|
||||
JPanel transactionPanel = createTransactionPanel(blockchainTable, transaction);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = row;
|
||||
c.weighty = 1;
|
||||
c.weightx = 1;
|
||||
c.anchor = GridBagConstraints.NORTHWEST;
|
||||
c.insets = new Insets(10, 10, 0, 10);
|
||||
transactionsPanel.add(transactionPanel, c);
|
||||
row++;
|
||||
}
|
||||
transactionsPanel.repaint();
|
||||
}
|
||||
|
||||
private JPanel createTransactionPanel(final BlockChainTable blockchainTable, final Transaction transaction) {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
JPanel transactionPanel = new JPanel(new GridBagLayout());
|
||||
transactionPanel.setBorder(BorderFactory.createLineBorder(Color.black));
|
||||
|
||||
JLabel senderLabel = new JLabel("Sender");
|
||||
senderLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(10, 0, 0, 0);
|
||||
transactionPanel.add(senderLabel, c);
|
||||
|
||||
JTextField sender = new JTextField(ByteUtil.toHexString(transaction.getSender()));
|
||||
highlightText(sender);
|
||||
sender.setEditable(false);
|
||||
sender.setBorder(null);
|
||||
sender.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(sender, c);
|
||||
|
||||
JLabel gasPriceLabel = new JLabel("Gas price");
|
||||
gasPriceLabel.setFont(plain);
|
||||
c.gridx = 2;
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(gasPriceLabel, c);
|
||||
|
||||
JTextField gasPrice = new JTextField(ByteUtil.toHexString(transaction.getGasPrice()));
|
||||
highlightText(gasPrice);
|
||||
gasPrice.setEditable(false);
|
||||
gasPrice.setBorder(null);
|
||||
gasPrice.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 0;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(gasPrice, c);
|
||||
|
||||
JLabel receiveAddressLabel = new JLabel("Receive address");
|
||||
receiveAddressLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
transactionPanel.add(receiveAddressLabel, c);
|
||||
|
||||
JTextField receiveAddress = new JTextField(ByteUtil.toHexString(transaction.getReceiveAddress()));
|
||||
highlightText(receiveAddress);
|
||||
receiveAddress.setEditable(false);
|
||||
receiveAddress.setBorder(null);
|
||||
receiveAddress.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 1;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(receiveAddress, c);
|
||||
|
||||
JLabel gasLimitLabel = new JLabel("Gas limit");
|
||||
gasLimitLabel.setFont(plain);
|
||||
c.gridx = 2;
|
||||
c.gridy = 1;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(gasLimitLabel, c);
|
||||
|
||||
JTextField gasLimit = new JTextField(ByteUtil.toHexString(transaction.getGasLimit()));
|
||||
highlightText(gasLimit);
|
||||
gasLimit.setEditable(false);
|
||||
gasLimit.setBorder(null);
|
||||
gasLimit.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 1;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(gasLimit, c);
|
||||
|
||||
JLabel hashLabel = new JLabel("Hash");
|
||||
hashLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
transactionPanel.add(hashLabel, c);
|
||||
|
||||
JTextField hash = new JTextField(ByteUtil.toHexString(transaction.getHash()));
|
||||
highlightText(hash);
|
||||
hash.setEditable(false);
|
||||
hash.setBorder(null);
|
||||
hash.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 2;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(hash, c);
|
||||
|
||||
JLabel valueLabel = new JLabel("Value");
|
||||
valueLabel.setFont(plain);
|
||||
c.gridx = 2;
|
||||
c.gridy = 2;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(valueLabel, c);
|
||||
|
||||
JTextField value = new JTextField(transaction.getValue() != null ? ByteUtil.toHexString(transaction.getValue()) : "");
|
||||
highlightText(value);
|
||||
value.setEditable(false);
|
||||
value.setBorder(null);
|
||||
value.setFont(plain);
|
||||
c.gridx = 3;
|
||||
c.gridy = 2;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(value, c);
|
||||
|
||||
JLabel nonceLabel = new JLabel("Nonce");
|
||||
nonceLabel.setFont(plain);
|
||||
c.gridx = 0;
|
||||
c.gridy = 3;
|
||||
c.insets = new Insets(0, 0, 0, 0);
|
||||
transactionPanel.add(nonceLabel, c);
|
||||
|
||||
JTextField nonce = new JTextField(ByteUtil.toHexString(transaction.getNonce()));
|
||||
highlightText(nonce);
|
||||
nonce.setEditable(false);
|
||||
nonce.setBorder(null);
|
||||
nonce.setFont(plain);
|
||||
c.gridx = 1;
|
||||
c.gridy = 3;
|
||||
c.insets = new Insets(0, 10, 0, 0);
|
||||
transactionPanel.add(nonce, c);
|
||||
|
||||
JButton data = new JButton("Data");
|
||||
data.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
if (transactionDataWindow == null)
|
||||
transactionDataWindow = new TransactionData(blockchainTable);
|
||||
transactionDataWindow.setData(transaction.getData());
|
||||
transactionDataWindow.setVisible(true);
|
||||
transactionDataWindow.highlightText(findText.getText(), painter);
|
||||
}
|
||||
|
||||
});
|
||||
data.setFont(plain);
|
||||
if (findText.getText().length() > 0 && ByteUtil.toHexString(transaction.getData()).contains(findText.getText())) {
|
||||
data.setBackground(HILIT_COLOR);
|
||||
}
|
||||
c.gridx = 3;
|
||||
c.gridy = 3;
|
||||
c.insets = new Insets(0, 0, 10, 0);
|
||||
transactionPanel.add(data, c);
|
||||
|
||||
return transactionPanel;
|
||||
}
|
||||
|
||||
private void highlightText(JTextField textField) {
|
||||
if (findText.getText().length() > 0 && textField.getText().contains(findText.getText())) {
|
||||
try {
|
||||
int end = textField.getText().indexOf(findText.getText()) + findText.getText().length();
|
||||
textField.getHighlighter().addHighlight(textField.getText().indexOf(findText.getText()), end, painter);
|
||||
} catch (BadLocationException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
BlockChainTable mainFrame = new BlockChainTable(null);
|
||||
mainFrame.setVisible(true);
|
||||
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 15/05/14 13:08
|
||||
*/
|
||||
public class TableCellLongTextRenderer extends JEditorPane implements TableCellRenderer{
|
||||
|
||||
protected static Border m_noFocusBorder;
|
||||
|
||||
public TableCellLongTextRenderer() {
|
||||
m_noFocusBorder = new EmptyBorder(1, 2, 1, 2);
|
||||
setOpaque(true);
|
||||
setBorder(m_noFocusBorder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
this.setText((String) value);
|
||||
this.setSelectedTextColor(Color.BLUE);
|
||||
// this.setWrapStyleWord(true);
|
||||
// this.setLineWrap(true);
|
||||
|
||||
setBackground(isSelected && !hasFocus ? table.getSelectionBackground() : table.getBackground());
|
||||
setForeground(isSelected && !hasFocus ? table.getSelectionForeground() : table.getForeground());
|
||||
setBorder(hasFocus? UIManager.getBorder("Table.focusCellHighlightBorder") : m_noFocusBorder);
|
||||
|
||||
//set the JTextArea to the width of the table column
|
||||
setSize(table.getColumnModel().getColumn(column).getWidth(), getPreferredSize().height);
|
||||
if (table.getRowHeight(row) != getPreferredSize().height) {
|
||||
//set the height of the table row to the calculated height of the JTextArea
|
||||
table.setRowHeight(row, getPreferredSize().height);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.util.ByteUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Highlighter;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Adrian Benko
|
||||
* Created on: 27/08/14 18:22
|
||||
*/
|
||||
public class TransactionData extends JFrame {
|
||||
|
||||
private JPanel topPanel;
|
||||
private JTextArea dataTextArea;
|
||||
|
||||
public TransactionData(BlockChainTable blockChainTable) {
|
||||
setTitle("Data");
|
||||
setSize(400, 400);
|
||||
setLocation(350, 200);
|
||||
setBackground(Color.gray);
|
||||
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
|
||||
// Create a panel to hold all other components
|
||||
topPanel = new JPanel(new BorderLayout());
|
||||
getContentPane().add(topPanel);
|
||||
|
||||
dataTextArea = new JTextArea();
|
||||
dataTextArea.setEditable(false);
|
||||
dataTextArea.setLineWrap(true);
|
||||
dataTextArea.setOpaque(false);
|
||||
dataTextArea.setWrapStyleWord(false);
|
||||
dataTextArea.setFont(BlockChainTable.plain);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(dataTextArea);
|
||||
topPanel.add(scrollPane, BorderLayout.CENTER);
|
||||
}
|
||||
|
||||
public void setData(byte[] data) {
|
||||
dataTextArea.setText(ByteUtil.toHexString(data));
|
||||
topPanel.repaint();
|
||||
}
|
||||
|
||||
public void highlightText(String findText, Highlighter.HighlightPainter painter) {
|
||||
if (findText.length() > 0 && dataTextArea.getText().contains(findText)) {
|
||||
int begin = dataTextArea.getText().indexOf(findText);
|
||||
int end = begin + findText.length();
|
||||
try {
|
||||
dataTextArea.getHighlighter().addHighlight(begin, end, painter);
|
||||
} catch (BadLocationException e) {
|
||||
}
|
||||
dataTextArea.setCaretPosition(end);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue