Removed ethereumj-studio.
This commit is contained in:
parent
1d3782c3be
commit
781e23ec70
|
@ -1,11 +0,0 @@
|
|||
|
||||
## ethereum-studio
|
||||
|
||||
To run the ethereumj-studio GUI:
|
||||
|
||||
- run `../gradlew run`, or
|
||||
- run `../gradlew shadowJar`, followed by `java -jar build/libs/ethereumj-studio-*-all.jar`
|
||||
|
||||
See ethereumj-studio in action here:
|
||||
|
||||
[![ScreenShot](http://i.imgur.com/FQiBihl.jpg)](https://www.youtube.com/watch?v=D5ok7jh7AOg)
|
|
@ -1,15 +0,0 @@
|
|||
plugins {
|
||||
id 'application'
|
||||
id 'com.github.johnrengelman.shadow' version '1.2.0'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
mainClassName = 'org.ethereum.gui.ToolBar'
|
||||
|
||||
dependencies {
|
||||
compile project(':ethereumj-core')
|
||||
compile "com.maxmind.geoip:geoip-api:1.2.11"
|
||||
compile "com.maxmind.geoip2:geoip2:0.6.0"
|
||||
compile "com.fifesoft:rsyntaxtextarea:2.5.0"
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
|
||||
init:
|
||||
|
||||
// Setting the storage value
|
||||
contract.storage[999] = 3
|
||||
|
||||
code:
|
||||
|
||||
// Using the storage on the call
|
||||
a = contract.storage[999]
|
||||
|
||||
if a > 0:
|
||||
contract.storage[999] = a - 1
|
||||
|
||||
// call to myself:
|
||||
send((tx.gas/10 * 8), contract.address, 0)
|
||||
else:
|
||||
stop
|
|
@ -1,34 +0,0 @@
|
|||
|
||||
|
||||
// the sample is good example how one can
|
||||
// save program that manage his own currency
|
||||
|
||||
init:
|
||||
|
||||
// this part run only on init stage
|
||||
// we are about to set the maxim
|
||||
// amount of currency
|
||||
contract.storage[0xcd2a3d9f938e13cd947ec05abc7fe734df8dd826] = 10000000
|
||||
code:
|
||||
|
||||
|
||||
// the currency manager
|
||||
// support two functions
|
||||
if msg.datasize == 1:
|
||||
|
||||
// 1. balance check
|
||||
addr = msg.data[0]
|
||||
return(contract.storage[addr])
|
||||
else:
|
||||
|
||||
// 2. balance manipulation
|
||||
from = msg.sender
|
||||
fromvalue = contract.storage[from]
|
||||
to = msg.data[0]
|
||||
value = msg.data[1]
|
||||
if fromvalue >= value:
|
||||
contract.storage[from] = fromvalue - value
|
||||
contract.storage[to] = contract.storage[to] + value
|
||||
return(1)
|
||||
else:
|
||||
return(0)
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
// The sample demonstrates how you
|
||||
// can simply create a program running
|
||||
// on top of chain and saving values for
|
||||
// futre use
|
||||
if !(contract.storage[msg.data[0]]):
|
||||
contract.storage[msg.data[0]] = msg.data[1]
|
||||
return(1)
|
||||
else:
|
||||
return(0)
|
|
@ -1,56 +0,0 @@
|
|||
package org.ethereum.geo;
|
||||
|
||||
import com.maxmind.geoip.Location;
|
||||
import com.maxmind.geoip.LookupService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 24.04.14
|
||||
*/
|
||||
public class IpGeoDB { // change
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(IpGeoDB.class);
|
||||
|
||||
static {
|
||||
try {
|
||||
File file = null;
|
||||
try {
|
||||
|
||||
String dir = System.getProperty("user.dir");
|
||||
String fileName = dir + "/config/GeoLiteCity.dat";
|
||||
file = new File(fileName);
|
||||
if (!file.exists()) {
|
||||
URL geiIpDBFile = ClassLoader
|
||||
.getSystemResource("GeoLiteCity.dat");
|
||||
file = new File(geiIpDBFile.toURI());
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
logger.error(th.getMessage(), th);
|
||||
System.exit(-1);
|
||||
}
|
||||
cl = new LookupService(file);
|
||||
} catch (Throwable e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private static LookupService cl;
|
||||
|
||||
public static Location getLocationForIp(InetAddress ip) {
|
||||
try {
|
||||
return cl.getLocation(ip);
|
||||
} catch (Throwable e) {
|
||||
// TODO: think about this exception, maybe you can do something more reasonable
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Denomination;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.facade.Repository;
|
||||
|
||||
import org.spongycastle.util.Arrays;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
public class AccountsListWindow extends JFrame {
|
||||
|
||||
private JTable tblAccountsDataTable;
|
||||
private AccountsDataAdapter adapter;
|
||||
|
||||
public AccountsListWindow() {
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
setTitle("Accounts List");
|
||||
setSize(700, 500);
|
||||
setLocation(50, 180);
|
||||
setResizable(false);
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
getContentPane().add(panel);
|
||||
|
||||
tblAccountsDataTable = new JTable();
|
||||
|
||||
adapter = new AccountsDataAdapter(new ArrayList<>());
|
||||
tblAccountsDataTable.setModel(adapter);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(tblAccountsDataTable);
|
||||
scrollPane.setPreferredSize(new Dimension(680, 490));
|
||||
panel.add(scrollPane);
|
||||
|
||||
loadAccounts();
|
||||
}
|
||||
|
||||
private void loadAccounts() {
|
||||
new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Repository repository = UIEthereumManager.ethereum.getRepository();
|
||||
Set<byte[]> keys = repository.getAccountsKeys();
|
||||
for (byte[] key : keys) {
|
||||
DataClass dc = new DataClass();
|
||||
dc.address = key;
|
||||
AccountState state = repository.getAccountState(dc.address);
|
||||
dc.accountState = state;
|
||||
|
||||
adapter.addDataPiece(dc);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private class AccountsDataAdapter extends AbstractTableModel {
|
||||
List<DataClass> data;
|
||||
|
||||
final String[] columns = new String[]{"Account", "Balance", "Is Contract"};
|
||||
|
||||
public AccountsDataAdapter(List<DataClass> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void addDataPiece(DataClass d) {
|
||||
data.add(d);
|
||||
this.fireTableRowsInserted(Math.min(data.size() - 2, 0), data.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
return columns[column];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCellEditable(int row, int column) { // custom isCellEditable function
|
||||
return column == 0 ? true : false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
if (columnIndex == 0) {
|
||||
return Hex.toHexString(data.get(rowIndex).address);
|
||||
} else if (columnIndex == 1) {
|
||||
if (data.get(rowIndex).accountState != null) {
|
||||
return Denomination.toFriendlyString(data.get(rowIndex).accountState.getBalance());
|
||||
}
|
||||
return "---";
|
||||
} else {
|
||||
if (data.get(rowIndex).accountState != null) {
|
||||
if (!Arrays.areEqual(data.get(rowIndex).accountState.getCodeHash(), HashUtil.EMPTY_DATA_HASH))
|
||||
return "Yes";
|
||||
}
|
||||
return "No";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class DataClass {
|
||||
public byte[] address;
|
||||
public AccountState accountState;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,856 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.facade.Blockchain;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.text.AbstractDocument;
|
||||
import javax.swing.text.AttributeSet;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.DefaultHighlighter;
|
||||
import javax.swing.text.DocumentFilter;
|
||||
import javax.swing.text.Highlighter;
|
||||
|
||||
/**
|
||||
* @author Adrian Benko
|
||||
* @since 27.08.14
|
||||
*/
|
||||
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 JPanel titlePanel;
|
||||
private JPanel blockPanel;
|
||||
private JPanel transactionsPanel;
|
||||
private JScrollPane scrollPane;
|
||||
|
||||
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();
|
||||
|
||||
foundBlocks = new ArrayList<>();
|
||||
painter = new DefaultHighlighter.DefaultHighlightPainter(HILIT_COLOR);
|
||||
|
||||
setTitle("Block Chain Table");
|
||||
setSize(900, 400);
|
||||
setLocation(315, 270);
|
||||
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();
|
||||
topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.PAGE_AXIS));
|
||||
getContentPane().add(topPanel, BorderLayout.LINE_START);
|
||||
|
||||
titlePanel = new JPanel(new FlowLayout());
|
||||
titlePanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 50));
|
||||
createTitlePanel(this);
|
||||
|
||||
blockPanel = new JPanel(new GridBagLayout());
|
||||
blockPanel.setMaximumSize(new Dimension(Short.MAX_VALUE, 160));
|
||||
createBlockPanel();
|
||||
|
||||
transactionsPanel = new JPanel(new GridBagLayout());
|
||||
scrollPane = new JScrollPane(transactionsPanel);
|
||||
scrollPane.setBorder(BorderFactory.createEmptyBorder());
|
||||
scrollPane.setAlignmentX(0);
|
||||
fillBlock(this);
|
||||
|
||||
titlePanel.setAlignmentX(0);
|
||||
topPanel.add(titlePanel);
|
||||
blockPanel.setAlignmentX(0);
|
||||
topPanel.add(blockPanel);
|
||||
|
||||
JLabel transactionsLabel = new JLabel("Transactions ");
|
||||
transactionsLabel.setFont(bold);
|
||||
transactionsLabel.setAlignmentX(0);
|
||||
transactionsLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
|
||||
topPanel.add(transactionsLabel);
|
||||
topPanel.add(scrollPane);
|
||||
|
||||
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;
|
||||
|
||||
Block block = UIEthereumManager.ethereum.getBlockchain().getBlockByNumber(lastFindIndex);
|
||||
StringSelection selection = new StringSelection(block.toString());
|
||||
Clipboard system = Toolkit.getDefaultToolkit().getSystemClipboard();
|
||||
system.setContents(selection, selection);
|
||||
}
|
||||
});
|
||||
|
||||
t = new Thread() {
|
||||
public void run() {
|
||||
running = true;
|
||||
while (running) {
|
||||
blocksCount.setText("" + UIEthereumManager.ethereum.getBlockchain().getSize());
|
||||
try {
|
||||
sleep(BLOCK_CHECK_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
t.start();
|
||||
}
|
||||
|
||||
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 < UIEthereumManager.ethereum.getBlockchain().getSize() - 1) {
|
||||
blockNum++;
|
||||
}
|
||||
} else if ("lastBlock".equals(e.getActionCommand())) {
|
||||
blockNum = UIEthereumManager.ethereum.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 < UIEthereumManager.ethereum.getBlockchain().getSize(); i++) {
|
||||
Block block = UIEthereumManager.ethereum.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 = UIEthereumManager.ethereum.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;
|
||||
|
||||
Blockchain blockchain = UIEthereumManager.ethereum.getBlockchain();
|
||||
long blockNum = Long.parseLong(blockNumberText.getText());
|
||||
if (blockNum > blockchain.getSize() - 1) {
|
||||
blockNum = blockchain.getSize() - 1;
|
||||
}
|
||||
Block block = blockchain.getBlockByNumber(blockNum);
|
||||
blockN.setText("" + block.getNumber());
|
||||
highlightText(blockN);
|
||||
minGasPrice.setText("" + 42);
|
||||
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();
|
||||
scrollPane.revalidate();
|
||||
}
|
||||
|
||||
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(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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,156 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.listener.EthereumListenerAdapter;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
|
||||
import org.fife.ui.rsyntaxtextarea.Token;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* A simple example showing how to modify the fonts and colors used in an
|
||||
* RSyntaxTextArea. There are two methods to do this - via the Java API, and via
|
||||
* an XML file. The latter method is preferred since it's more modular, and
|
||||
* provides a way for your users to customize RSTA in your application.<p>
|
||||
*
|
||||
* This example uses RSyntaxTextArea 2.0.1.<p>
|
||||
*
|
||||
* Project Home: http://fifesoft.com/rsyntaxtextarea<br>
|
||||
* Downloads: https://sourceforge.net/projects/rsyntaxtextarea
|
||||
*/
|
||||
public class ConnectionConsoleWindow extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private boolean autoScroll = false;
|
||||
private RSyntaxTextArea textArea;
|
||||
private ToolBar toolBar = null;
|
||||
|
||||
/**
|
||||
* ERROR (exceptions) WARN (when something happens that's not supposed to)
|
||||
* INFO (wire output)
|
||||
* DEBUG (test/displaying intermediate values),
|
||||
* TRACE (start/end method)
|
||||
*/
|
||||
public ConnectionConsoleWindow(ToolBar toolBar) {
|
||||
final ConnectionConsoleWindow thisConsole = this;
|
||||
this.toolBar = toolBar;
|
||||
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
addCloseAction();
|
||||
|
||||
JPanel cp = new JPanel(new BorderLayout());
|
||||
|
||||
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance();
|
||||
atmf.putMapping("text/console", "org.ethereum.gui.ConsoleTokenMaker");
|
||||
|
||||
textArea = new RSyntaxTextArea(16, 44);
|
||||
textArea.setSyntaxEditingStyle("text/console");
|
||||
// textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_LISP);
|
||||
textArea.setCodeFoldingEnabled(true);
|
||||
textArea.setAntiAliasingEnabled(true);
|
||||
|
||||
changeStyleProgrammatically();
|
||||
RTextScrollPane sp = new RTextScrollPane(textArea);
|
||||
|
||||
cp.add(sp);
|
||||
|
||||
setContentPane(cp);
|
||||
setTitle("Connection Console");
|
||||
// setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
pack();
|
||||
setLocation(802, 460);
|
||||
|
||||
if (CONFIG.peerDiscovery())
|
||||
UIEthereumManager.ethereum.startPeerDiscovery();
|
||||
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
|
||||
UIEthereumManager.ethereum.connect(SystemProperties.CONFIG.activePeerIP(),
|
||||
SystemProperties.CONFIG.activePeerPort());
|
||||
}
|
||||
};
|
||||
|
||||
UIEthereumManager.ethereum.addListener(new EthereumListenerAdapter() {
|
||||
@Override
|
||||
public void trace(final String output) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
textArea.append(output);
|
||||
textArea.append("\n");
|
||||
|
||||
if (autoScroll)
|
||||
textArea.setCaretPosition(textArea.getText().length());
|
||||
});
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
|
||||
private void changeStyleProgrammatically() {
|
||||
|
||||
// Set the font for all token types.
|
||||
setFont(textArea, new Font("Courier New", Font.PLAIN, 12));
|
||||
|
||||
// Change a few things here and there.
|
||||
SyntaxScheme scheme = textArea.getSyntaxScheme();
|
||||
scheme.getStyle(Token.RESERVED_WORD).background = Color.white;
|
||||
scheme.getStyle(Token.RESERVED_WORD).foreground = Color.MAGENTA.darker().darker();
|
||||
|
||||
scheme.getStyle(Token.DATA_TYPE).foreground = Color.blue;
|
||||
scheme.getStyle(Token.LITERAL_STRING_DOUBLE_QUOTE).underline = true;
|
||||
scheme.getStyle(Token.LITERAL_NUMBER_HEXADECIMAL).underline = true;
|
||||
scheme.getStyle(Token.LITERAL_NUMBER_HEXADECIMAL).background = Color.pink;
|
||||
|
||||
scheme.getStyle(Token.COMMENT_EOL).font = new Font("Georgia",
|
||||
Font.ITALIC, 10);
|
||||
|
||||
textArea.revalidate();
|
||||
}
|
||||
|
||||
public static void setFont(RSyntaxTextArea textArea, Font font) {
|
||||
if (font != null) {
|
||||
SyntaxScheme ss = textArea.getSyntaxScheme();
|
||||
ss = (SyntaxScheme) ss.clone();
|
||||
for (int i = 0; i < ss.getStyleCount(); i++) {
|
||||
if (ss.getStyle(i) != null) {
|
||||
ss.getStyle(i).font = font;
|
||||
}
|
||||
}
|
||||
textArea.setSyntaxScheme(ss);
|
||||
textArea.setFont(font);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
toolBar.logToggle.setSelected(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Start all Swing applications on the EDT.
|
||||
SwingUtilities.invokeLater(() -> new ConnectionConsoleWindow(null).setVisible(true));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1,959 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMaker;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
|
||||
import org.fife.ui.rsyntaxtextarea.Token;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.text.Segment;
|
||||
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 24.04.14
|
||||
*/
|
||||
public class ConsoleTokenMaker extends AbstractTokenMaker {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("gui");
|
||||
|
||||
protected final String operators = "+-*/%!=<>^&|?:";
|
||||
|
||||
protected final String separators = "()[]{}";
|
||||
|
||||
protected final String separators2 = ".,;"; // Characters you don't want syntax highlighted but separate identifiers.
|
||||
|
||||
protected final String hexCharacters = "0123456789ABCDEFabcdef";
|
||||
|
||||
protected final String numberEndChars = "FfLl"; // Characters used to specify literal number types.
|
||||
|
||||
private int currentTokenStart;
|
||||
private int currentTokenType;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public ConsoleTokenMaker() {
|
||||
super(); // Initializes tokensToHighlight.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks the token to give it the exact ID it deserves before
|
||||
* being passed up to the super method.
|
||||
*
|
||||
* @param segment <code>Segment</code> to get text from.
|
||||
* @param start Start offset in <code>segment</code> of token.
|
||||
* @param end End offset in <code>segment</code> of token.
|
||||
* @param tokenType The token's type.
|
||||
* @param startOffset The offset in the document at which the token occurs.
|
||||
*/
|
||||
public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) {
|
||||
|
||||
switch (tokenType) {
|
||||
// Since reserved words, functions, and data types are all passed
|
||||
// into here as "identifiers," we have to see what the token
|
||||
// really is...
|
||||
case Token.IDENTIFIER:
|
||||
int value = wordsToHighlight.get(segment, start, end);
|
||||
if (value != -1)
|
||||
tokenType = value;
|
||||
break;
|
||||
case Token.WHITESPACE:
|
||||
case Token.SEPARATOR:
|
||||
case Token.OPERATOR:
|
||||
case Token.ERROR_IDENTIFIER:
|
||||
case Token.ERROR_NUMBER_FORMAT:
|
||||
case Token.ERROR_STRING_DOUBLE:
|
||||
case Token.ERROR_CHAR:
|
||||
case Token.COMMENT_EOL:
|
||||
case Token.COMMENT_MULTILINE:
|
||||
case Token.LITERAL_BOOLEAN:
|
||||
case Token.LITERAL_NUMBER_DECIMAL_INT:
|
||||
case Token.LITERAL_NUMBER_FLOAT:
|
||||
case Token.LITERAL_NUMBER_HEXADECIMAL:
|
||||
break;
|
||||
case Token.LITERAL_STRING_DOUBLE_QUOTE:
|
||||
case Token.LITERAL_CHAR:
|
||||
break;
|
||||
|
||||
default:
|
||||
logger.error("Unknown tokenType: '" + tokenType + "'");
|
||||
tokenType = Token.IDENTIFIER;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
super.addToken(segment, start, end, tokenType, startOffset);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the text to place at the beginning and end of a
|
||||
* line to "comment" it in a this programming language.
|
||||
*
|
||||
* @return The start and end strings to add to a line to "comment"
|
||||
* it out.
|
||||
*/
|
||||
public String[] getLineCommentStartAndEnd() {
|
||||
return new String[]{"//", null};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the words to highlight for the JavaScript programming language.
|
||||
*
|
||||
* @return A <code>TokenMap</code> containing the words to highlight for
|
||||
* the JavaScript programming language.
|
||||
* @see org.fife.ui.rsyntaxtextarea.AbstractTokenMaker#getWordsToHighlight
|
||||
*/
|
||||
public TokenMap getWordsToHighlight() {
|
||||
|
||||
TokenMap tokenMap = new TokenMap(52);
|
||||
|
||||
int reservedWord = Token.RESERVED_WORD;
|
||||
tokenMap.put("connecting", reservedWord);
|
||||
|
||||
int literalBoolean = Token.LITERAL_BOOLEAN;
|
||||
tokenMap.put("false", literalBoolean);
|
||||
tokenMap.put("true", literalBoolean);
|
||||
|
||||
int dataType = Token.DATA_TYPE;
|
||||
tokenMap.put("boolean", dataType);
|
||||
|
||||
return tokenMap;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> always as JavaScript uses curly braces
|
||||
* to denote code blocks.
|
||||
*
|
||||
* @return <code>true</code> always.
|
||||
*/
|
||||
public boolean getCurlyBracesDenoteCodeBlocks() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the first token in the linked list of tokens generated
|
||||
* from <code>text</code>. This method must be implemented by
|
||||
* subclasses so they can correctly implement syntax highlighting.
|
||||
*
|
||||
* @param text The text from which to get tokens.
|
||||
* @param initialTokenType The token type we should start with.
|
||||
* @param startOffset The offset into the document at which
|
||||
* <code>text</code> starts.
|
||||
* @return The first <code>Token</code> in a linked list representing
|
||||
* the syntax highlighted text.
|
||||
*/
|
||||
public Token getTokenList(Segment text, int initialTokenType,
|
||||
int startOffset) {
|
||||
|
||||
|
||||
resetTokenList();
|
||||
|
||||
char[] array = text.array;
|
||||
int offset = text.offset;
|
||||
int count = text.count;
|
||||
int end = offset + count;
|
||||
|
||||
// See, when we find a token, its starting position is always of the
|
||||
// form: 'startOffset + (currentTokenStart-offset)'; but since
|
||||
// startOffset and offset are constant, tokens' starting positions
|
||||
// become: 'newStartOffset+currentTokenStart' for one less subtraction
|
||||
// operation.
|
||||
int newStartOffset = startOffset - offset;
|
||||
|
||||
currentTokenStart = offset;
|
||||
currentTokenType = initialTokenType;
|
||||
boolean backslash = false;
|
||||
boolean numContainsExponent = false;
|
||||
boolean numContainsEndCharacter = false;
|
||||
|
||||
for (int i = offset; i < end; i++) {
|
||||
|
||||
char c = array[i];
|
||||
|
||||
switch (currentTokenType) {
|
||||
|
||||
case Token.NULL:
|
||||
|
||||
currentTokenStart = i; // Starting a new token here.
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
if (backslash) { // Escaped double quote => call '"' an identifier..
|
||||
addToken(text, currentTokenStart, i, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
backslash = false;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\'':
|
||||
if (backslash) { // Escaped single quote => call '\'' an identifier.
|
||||
addToken(text, currentTokenStart, i, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
backslash = false;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
}
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i, Token.IDENTIFIER, newStartOffset + currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = !backslash;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (RSyntaxUtilities.isDigit(c)) {
|
||||
currentTokenType = Token.LITERAL_NUMBER_DECIMAL_INT;
|
||||
break;
|
||||
} else if (RSyntaxUtilities.isLetter(c) || c == '_') {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
int indexOf = operators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
break;
|
||||
}
|
||||
indexOf = separators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i, Token.SEPARATOR, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
indexOf = separators2.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
case Token.WHITESPACE:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
break; // Still whitespace.
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true; // Previous char whitespace => this must be first backslash.
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is space.
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is space.
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
default: // Add the whitespace token and start anew.
|
||||
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
|
||||
if (RSyntaxUtilities.isDigit(c)) {
|
||||
currentTokenType = Token.LITERAL_NUMBER_DECIMAL_INT;
|
||||
break;
|
||||
} else if (RSyntaxUtilities.isLetter(c) || c == '_') {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
int indexOf = operators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
break;
|
||||
}
|
||||
indexOf = separators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
indexOf = separators2.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_IDENTIFIER;
|
||||
}
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
default: // Should never happen
|
||||
|
||||
|
||||
case Token.LITERAL_NUMBER_HEXADECIMAL:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL, newStartOffset
|
||||
+ currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL, newStartOffset
|
||||
+ currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL, newStartOffset
|
||||
+ currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL, newStartOffset
|
||||
+ currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (c == 'e') { // Exponent.
|
||||
if (numContainsExponent == false) {
|
||||
numContainsExponent = true;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
int indexOf = hexCharacters.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
break; // Still a hexadecimal number.
|
||||
}
|
||||
indexOf = numberEndChars.indexOf(c);
|
||||
if (indexOf > -1) { // Numbers can end in 'f','F','l','L', etc.
|
||||
if (numContainsEndCharacter == true) {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
} else {
|
||||
numContainsEndCharacter = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL,
|
||||
newStartOffset + currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
break;
|
||||
}
|
||||
indexOf = separators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL,
|
||||
newStartOffset + currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
indexOf = separators2.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_HEXADECIMAL,
|
||||
newStartOffset + currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, the token is an error.
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case Token.IDENTIFIER:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (RSyntaxUtilities.isLetterOrDigit(c) || c == '_') {
|
||||
break; // Still an identifier of some type.
|
||||
}
|
||||
int indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
break;
|
||||
}
|
||||
indexOf = separators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
indexOf = separators2.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_IDENTIFIER;
|
||||
}
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
case Token.LITERAL_NUMBER_DECIMAL_INT:
|
||||
|
||||
// Reset our boolean states if we only have one digit char before
|
||||
// the current one.
|
||||
if (currentTokenStart == i - 1) {
|
||||
numContainsExponent = false;
|
||||
numContainsEndCharacter = false;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset
|
||||
+ currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset
|
||||
+ currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset
|
||||
+ currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT, newStartOffset
|
||||
+ currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (RSyntaxUtilities.isDigit(c)) {
|
||||
break; // Still a literal number.
|
||||
} else if (c == 'e') { // Exponent.
|
||||
if (numContainsExponent == false) {
|
||||
numContainsExponent = true;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
}
|
||||
break;
|
||||
} else if (c == '.') { // Decimal point.
|
||||
if (numContainsExponent == true) {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
} else {
|
||||
currentTokenType = Token.LITERAL_NUMBER_FLOAT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
int indexOf = numberEndChars.indexOf(c);
|
||||
if (indexOf > -1) { // Numbers can end in 'f','F','l','L', etc.
|
||||
if (numContainsEndCharacter == true) {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
} else {
|
||||
numContainsEndCharacter = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT,
|
||||
newStartOffset + currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
break;
|
||||
}
|
||||
indexOf = separators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT,
|
||||
newStartOffset + currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
indexOf = separators2.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_DECIMAL_INT,
|
||||
newStartOffset + currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, the token is an error.
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
case Token.LITERAL_NUMBER_FLOAT:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (RSyntaxUtilities.isDigit(c)) {
|
||||
break; // Still a literal number.
|
||||
} else if (c == 'e') { // Exponent.
|
||||
if (numContainsExponent == false) {
|
||||
numContainsExponent = true;
|
||||
} else {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
}
|
||||
break;
|
||||
} else if (c == '.') { // Second decimal point; must catch now because it's a "separator"
|
||||
// below.
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
break;
|
||||
}
|
||||
int indexOf = numberEndChars.indexOf(c);
|
||||
if (indexOf > -1) { // Numbers can end in 'f','F','l','L', etc.
|
||||
if (numContainsEndCharacter == true) {
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
} else {
|
||||
numContainsEndCharacter = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
break;
|
||||
}
|
||||
indexOf = separators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
indexOf = separators2.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.LITERAL_NUMBER_FLOAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, the token is an error.
|
||||
currentTokenType = Token.ERROR_NUMBER_FORMAT;
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case Token.COMMENT_MULTILINE:
|
||||
|
||||
// Find either end of MLC or end of the current line.
|
||||
while (i < end - 1) {
|
||||
if (array[i] == '*' && array[i + 1] == '/') {
|
||||
addToken(text, currentTokenStart, i + 1, Token.COMMENT_MULTILINE, newStartOffset +
|
||||
currentTokenStart);
|
||||
i = i + 1;
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = false; // Backslashes can't accumulate before and after a comment...
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Token.COMMENT_EOL:
|
||||
i = end - 1;
|
||||
addToken(text, currentTokenStart, i, Token.COMMENT_EOL, newStartOffset + currentTokenStart);
|
||||
// We need to set token type to null so at the bottom we don't add one more token.
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
// We need this state because comments always start with '/', which is an operator.
|
||||
// Note that when we enter this state, the PREVIOUS character was an operator.
|
||||
case Token.OPERATOR:
|
||||
|
||||
if (array[i - 1] == '/') { // Possibility of comments.
|
||||
|
||||
if (c == '*') {
|
||||
currentTokenType = Token.COMMENT_MULTILINE;
|
||||
break;
|
||||
} else if (c == '/') {
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
i = end - 1; // Since we know the rest of the line is in this token.
|
||||
} else {
|
||||
// We MUST add the token at the previous char now; if we don't and let
|
||||
// operators accumulate before we print them, we will mess up syntax
|
||||
// highlighting if we get an end-of-line comment.
|
||||
addToken(text, currentTokenStart, i - 1, Token.OPERATOR, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
i = i - 1;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
addToken(text, currentTokenStart, i - 1, Token.OPERATOR, newStartOffset + currentTokenStart);
|
||||
|
||||
// Hack to keep code size down...
|
||||
i--;
|
||||
currentTokenType = Token.NULL;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case Token.ERROR_IDENTIFIER:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true; // Must be first backslash in a row since previous character
|
||||
// identifier char.
|
||||
break;
|
||||
|
||||
default:
|
||||
int indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
}
|
||||
indexOf = separators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
indexOf = separators2.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
case Token.ERROR_NUMBER_FORMAT:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case '\'': // Don't need to worry about backslashes as previous char is non-backslash.
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_CHAR;
|
||||
backslash = false;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
case '\\':
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
backslash = true; // Must be first backslash in a row since previous char is a number
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
// Could be going into hexadecimal.
|
||||
int indexOf = hexCharacters.indexOf(c);
|
||||
if (indexOf > -1 && (i - currentTokenStart == 2 && array[i - 1] == 'x' && array[i - 2] ==
|
||||
'0')) {
|
||||
currentTokenType = Token.LITERAL_NUMBER_HEXADECIMAL;
|
||||
break;
|
||||
}
|
||||
|
||||
indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.OPERATOR;
|
||||
}
|
||||
indexOf = separators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
indexOf = separators2.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.ERROR_NUMBER_FORMAT, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
|
||||
} // End of switch (c).
|
||||
|
||||
break;
|
||||
|
||||
case Token.ERROR_CHAR:
|
||||
|
||||
if (c == '\\') {
|
||||
backslash = !backslash; // Okay because if we got in here, backslash was initially false.
|
||||
} else {
|
||||
|
||||
if (c == '\'' && !backslash) {
|
||||
addToken(text, currentTokenStart, i, Token.LITERAL_CHAR, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
// backslash is definitely false when we leave.
|
||||
}
|
||||
|
||||
backslash = false; // Need to set backslash to false here as a character was typed.
|
||||
|
||||
}
|
||||
// Otherwise, we're still an unclosed char...
|
||||
|
||||
break;
|
||||
|
||||
case Token.ERROR_STRING_DOUBLE:
|
||||
|
||||
if (c == '\\') {
|
||||
backslash = !backslash; // Okay because if we got in here, backslash was initially false.
|
||||
} else {
|
||||
if (c == '"' && !backslash) {
|
||||
addToken(text, currentTokenStart, i, Token.LITERAL_STRING_DOUBLE_QUOTE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
// backslash is definitely false when we leave.
|
||||
}
|
||||
|
||||
backslash = false; // Need to set backslash to false here as a character was typed.
|
||||
|
||||
}
|
||||
// Otherwise, we're still an unclosed string...
|
||||
|
||||
break;
|
||||
|
||||
} // End of switch (currentTokenType).
|
||||
|
||||
} // End of for (int i=offset; i<end; i++).
|
||||
|
||||
// Deal with the (possibly there) last token.
|
||||
if (currentTokenType != Token.NULL) {
|
||||
addToken(text, currentTokenStart, end - 1, currentTokenType, newStartOffset + currentTokenStart);
|
||||
}
|
||||
if (currentTokenType != Token.COMMENT_MULTILINE) {
|
||||
addNullToken();
|
||||
}
|
||||
|
||||
|
||||
// Return the first token in our linked list.
|
||||
return firstToken;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,504 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Account;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.core.Wallet;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EtchedBorder;
|
||||
import javax.swing.plaf.ComboBoxUI;
|
||||
import javax.swing.plaf.basic.BasicComboPopup;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 18.05.14
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class ContractCallDialog extends JDialog implements MessageAwareDialog {
|
||||
|
||||
private static final long serialVersionUID = -7561153561155037293L;
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("ui");
|
||||
|
||||
private ContractCallDialog dialog;
|
||||
private JComboBox<AccountWrapper> creatorAddressCombo;
|
||||
private final JTextField gasInput;
|
||||
private final JTextField contractAddrInput;
|
||||
|
||||
private JScrollPane contractDataInput;
|
||||
private JTextArea msgDataTA;
|
||||
|
||||
private JLabel statusMsg = null;
|
||||
private JLabel playLabel = null;
|
||||
private JLabel rejectLabel = null;
|
||||
private JLabel approveLabel = null;
|
||||
|
||||
public ContractCallDialog(Frame parent) {
|
||||
super(parent, "Call Contract: ", false);
|
||||
dialog = this;
|
||||
|
||||
contractAddrInput = new JTextField(5);
|
||||
GUIUtils.addStyle(contractAddrInput, "Contract Address: ");
|
||||
contractAddrInput.addFocusListener(new FocusAdapter() {
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
|
||||
SwingUtilities.invokeLater(ContractCallDialog.this::populateContractDetails);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
contractAddrInput.setBounds(70, 30, 350, 45);
|
||||
this.getContentPane().add(contractAddrInput);
|
||||
|
||||
gasInput = new JTextField(5);
|
||||
GUIUtils.addStyle(gasInput, "Gas: ");
|
||||
|
||||
msgDataTA = new JTextArea();
|
||||
msgDataTA.setLineWrap(true);
|
||||
contractDataInput = new JScrollPane(msgDataTA);
|
||||
GUIUtils.addStyle(msgDataTA, null, false);
|
||||
GUIUtils.addStyle(contractDataInput, "Input:");
|
||||
|
||||
msgDataTA.setText("");
|
||||
msgDataTA.setCaretPosition(0);
|
||||
|
||||
this.getContentPane().setBackground(Color.WHITE);
|
||||
this.getContentPane().setLayout(null);
|
||||
|
||||
contractDataInput.setBounds(70, 80, 350, 165);
|
||||
this.getContentPane().add(contractDataInput);
|
||||
|
||||
gasInput.setBounds(330, 260, 90, 45);
|
||||
this.getContentPane().add(gasInput);
|
||||
|
||||
URL rejectIconURL = ClassLoader.getSystemResource("buttons/reject.png");
|
||||
ImageIcon rejectIcon = new ImageIcon(rejectIconURL);
|
||||
rejectLabel = new JLabel(rejectIcon);
|
||||
rejectLabel.setToolTipText("Cancel");
|
||||
rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
URL playIconURL = ClassLoader.getSystemResource("buttons/play.png");
|
||||
ImageIcon playIcon = new ImageIcon(playIconURL);
|
||||
playLabel = new JLabel(playIcon);
|
||||
playLabel.setToolTipText("Play Drafted");
|
||||
playLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
playLabel.addMouseListener(
|
||||
new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
ContractCallDialog.this.playContractCall();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
playLabel.setBounds(438, 100, 42, 42);
|
||||
this.getContentPane().add(playLabel);
|
||||
|
||||
JLabel statusMessage = new JLabel("");
|
||||
statusMessage.setBounds(50, 360, 400, 50);
|
||||
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.statusMsg = statusMessage;
|
||||
this.getContentPane().add(statusMessage);
|
||||
|
||||
rejectLabel.setBounds(260, 325, 45, 45);
|
||||
this.getContentPane().add(rejectLabel);
|
||||
rejectLabel.setVisible(true);
|
||||
rejectLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
dialog.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
URL approveIconURL = ClassLoader.getSystemResource("buttons/approve.png");
|
||||
ImageIcon approveIcon = new ImageIcon(approveIconURL);
|
||||
approveLabel = new JLabel(approveIcon);
|
||||
approveLabel.setToolTipText("Submit the transaction");
|
||||
approveLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
approveLabel.setBounds(200, 325, 45, 45);
|
||||
this.getContentPane().add(approveLabel);
|
||||
approveLabel.setVisible(true);
|
||||
|
||||
approveLabel.addMouseListener(
|
||||
new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
submitContractCall();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
gasInput.setText("1000");
|
||||
|
||||
JComboBox<AccountWrapper> creatorAddressCombo = new JComboBox<AccountWrapper>() {
|
||||
private static final long serialVersionUID = -3748305421049121671L;
|
||||
|
||||
@Override
|
||||
public ComboBoxUI getUI() {
|
||||
return super.getUI();
|
||||
}
|
||||
};
|
||||
creatorAddressCombo.setOpaque(true);
|
||||
creatorAddressCombo.setEnabled(true);
|
||||
|
||||
creatorAddressCombo.setBackground(Color.WHITE);
|
||||
creatorAddressCombo.setFocusable(false);
|
||||
|
||||
this.creatorAddressCombo = creatorAddressCombo;
|
||||
|
||||
final Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
JComponent editor = (JComponent) (creatorAddressCombo.getEditor().getEditorComponent());
|
||||
editor.setForeground(Color.RED);
|
||||
|
||||
Wallet wallet = UIEthereumManager.ethereum.getWallet();
|
||||
Collection<Account> accounts = wallet.getAccountCollection();
|
||||
|
||||
for (Account account : accounts) {
|
||||
creatorAddressCombo.addItem(new AccountWrapper(account));
|
||||
}
|
||||
|
||||
creatorAddressCombo.setRenderer(new DefaultListCellRenderer() {
|
||||
private static final long serialVersionUID = 6100091092527477892L;
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
setBackground(Color.WHITE);
|
||||
setForeground(new Color(143, 170, 220));
|
||||
setFont(new Font("Monospaced", 0, 13));
|
||||
setBorder(BorderFactory.createEmptyBorder());
|
||||
super.paint(g);
|
||||
}
|
||||
});
|
||||
|
||||
creatorAddressCombo.setPopupVisible(false);
|
||||
|
||||
Object child = creatorAddressCombo.getAccessibleContext().getAccessibleChild(0);
|
||||
BasicComboPopup popup = (BasicComboPopup) child;
|
||||
|
||||
JList list = popup.getList();
|
||||
list.setSelectionBackground(Color.cyan);
|
||||
list.setBorder(null);
|
||||
|
||||
for (int i = 0; i < creatorAddressCombo.getComponentCount(); i++) {
|
||||
if (creatorAddressCombo.getComponent(i) instanceof CellRendererPane) {
|
||||
CellRendererPane crp = ((CellRendererPane) (creatorAddressCombo.getComponent(i)));
|
||||
}
|
||||
if (creatorAddressCombo.getComponent(i) instanceof AbstractButton) {
|
||||
((AbstractButton) creatorAddressCombo.getComponent(i)).setBorder(line);
|
||||
}
|
||||
}
|
||||
creatorAddressCombo.setBounds(70, 267, 230, 36);
|
||||
this.getContentPane().add(creatorAddressCombo);
|
||||
|
||||
this.getContentPane().revalidate();
|
||||
this.getContentPane().repaint();
|
||||
this.setResizable(false);
|
||||
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
private void populateContractDetails() {
|
||||
byte[] addr = Utils.addressStringToBytes(contractAddrInput.getText());
|
||||
if (addr == null) {
|
||||
alertStatusMsg("Not a valid contract address");
|
||||
return;
|
||||
}
|
||||
|
||||
ContractDetails contractDetails = UIEthereumManager.ethereum
|
||||
.getRepository().getContractDetails(addr);
|
||||
if (contractDetails == null) {
|
||||
alertStatusMsg("No contract for that address");
|
||||
return;
|
||||
}
|
||||
|
||||
final byte[] programCode = contractDetails.getCode();
|
||||
if (programCode == null || programCode.length == 0) {
|
||||
alertStatusMsg("Such account exist but no code in the db");
|
||||
return;
|
||||
}
|
||||
|
||||
final Map storageMap = contractDetails.getStorage();
|
||||
|
||||
contractDataInput.setBounds(70, 80, 350, 145);
|
||||
contractDataInput.setViewportView(msgDataTA);
|
||||
|
||||
URL expandIconURL = ClassLoader.getSystemResource("buttons/add-23x23.png");
|
||||
ImageIcon expandIcon = new ImageIcon(expandIconURL);
|
||||
final JLabel expandLabel = new JLabel(expandIcon);
|
||||
expandLabel.setToolTipText("Cancel");
|
||||
expandLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
expandLabel.setBounds(235, 232, 23, 23);
|
||||
this.getContentPane().add(expandLabel);
|
||||
expandLabel.setVisible(true);
|
||||
|
||||
final Border border = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
|
||||
final JPanel detailPanel = new JPanel();
|
||||
detailPanel.setBorder(border);
|
||||
detailPanel.setBounds(135, 242, 230, 2);
|
||||
|
||||
final JPanel spacer = new JPanel();
|
||||
spacer.setForeground(Color.white);
|
||||
spacer.setBackground(Color.white);
|
||||
spacer.setBorder(null);
|
||||
spacer.setBounds(225, 232, 40, 20);
|
||||
|
||||
this.getContentPane().add(spacer);
|
||||
this.getContentPane().add(detailPanel);
|
||||
|
||||
expandLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
ContractCallDialog.this.setSize(500, 530);
|
||||
|
||||
ContractCallDialog.this.creatorAddressCombo.setBounds(70, 367, 230, 36);
|
||||
ContractCallDialog.this.gasInput.setBounds(330, 360, 90, 45);
|
||||
ContractCallDialog.this.rejectLabel.setBounds(260, 425, 45, 45);
|
||||
ContractCallDialog.this.approveLabel.setBounds(200, 425, 45, 45);
|
||||
ContractCallDialog.this.statusMsg.setBounds(50, 460, 400, 50);
|
||||
|
||||
spacer.setVisible(false);
|
||||
expandLabel.setVisible(false);
|
||||
detailPanel.setVisible(false);
|
||||
|
||||
JTextField contractCode = new JTextField(15);
|
||||
contractCode.setText(Hex.toHexString(programCode));
|
||||
GUIUtils.addStyle(contractCode, "Code: ");
|
||||
contractCode.setBounds(70, 230, 350, 45);
|
||||
|
||||
JTable storage = new JTable(2, 2);
|
||||
storage.setTableHeader(null);
|
||||
storage.setShowGrid(false);
|
||||
storage.setIntercellSpacing(new Dimension(15, 0));
|
||||
storage.setCellSelectionEnabled(false);
|
||||
GUIUtils.addStyle(storage);
|
||||
|
||||
JTableStorageModel tableModel = new JTableStorageModel(storageMap);
|
||||
storage.setModel(tableModel);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(storage);
|
||||
scrollPane.setBorder(null);
|
||||
scrollPane.getViewport().setBackground(Color.WHITE);
|
||||
scrollPane.setBounds(70, 290, 350, 50);
|
||||
|
||||
|
||||
ContractCallDialog.this.getContentPane().add(contractCode);
|
||||
ContractCallDialog.this.getContentPane().add(scrollPane);
|
||||
}
|
||||
});
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
private void playContractCall() {
|
||||
byte[] addr = Utils.addressStringToBytes(contractAddrInput.getText());
|
||||
if (addr == null) {
|
||||
alertStatusMsg("Not a valid contract address");
|
||||
return;
|
||||
}
|
||||
|
||||
ContractDetails contractDetails = UIEthereumManager.ethereum
|
||||
.getRepository().getContractDetails(addr);
|
||||
if (contractDetails == null) {
|
||||
alertStatusMsg("No contract for that address");
|
||||
return;
|
||||
}
|
||||
|
||||
final byte[] programCode = contractDetails.getCode();
|
||||
if (programCode == null || programCode.length == 0) {
|
||||
alertStatusMsg("Such account exist but no code in the db");
|
||||
return;
|
||||
}
|
||||
|
||||
Transaction tx = createTransaction();
|
||||
if (tx == null) return;
|
||||
|
||||
Block lastBlock = UIEthereumManager.ethereum.getBlockchain().getBestBlock();
|
||||
ProgramPlayDialog.createAndShowGUI(programCode, tx, lastBlock);
|
||||
}
|
||||
|
||||
protected JRootPane createRootPane() {
|
||||
|
||||
Container parent = this.getParent();
|
||||
|
||||
if (parent != null) {
|
||||
Dimension parentSize = parent.getSize();
|
||||
Point p = parent.getLocation();
|
||||
setLocation(p.x + parentSize.width / 4, p.y + 10);
|
||||
}
|
||||
|
||||
JRootPane rootPane = new JRootPane();
|
||||
KeyStroke stroke = KeyStroke.getKeyStroke("ESCAPE");
|
||||
Action actionListener = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
dispose();
|
||||
}
|
||||
};
|
||||
InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
inputMap.put(stroke, "ESCAPE");
|
||||
rootPane.getActionMap().put("ESCAPE", actionListener);
|
||||
|
||||
this.setSize(500, 430);
|
||||
|
||||
return rootPane;
|
||||
}
|
||||
|
||||
public void infoStatusMsg(String text) {
|
||||
this.statusMsg.setForeground(Color.GREEN.darker().darker());
|
||||
this.statusMsg.setText(text);
|
||||
}
|
||||
|
||||
public void alertStatusMsg(String text) {
|
||||
this.statusMsg.setForeground(Color.RED);
|
||||
this.statusMsg.setText(text);
|
||||
}
|
||||
|
||||
public void submitContractCall() {
|
||||
|
||||
if (!UIEthereumManager.ethereum.isConnected()) {
|
||||
dialog.alertStatusMsg("Not connected to any peer");
|
||||
return;
|
||||
}
|
||||
|
||||
Transaction tx = createTransaction();
|
||||
if (tx == null) return;
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("tx.hash: {}", (new BigInteger(tx.getHash()).toString(16)));
|
||||
}
|
||||
// SwingWorker
|
||||
DialogWorker worker = new DialogWorker(tx, this);
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
private Transaction createTransaction() {
|
||||
|
||||
byte[] data;
|
||||
if (!msgDataTA.getText().trim().equals("")) {
|
||||
Object[] lexaList = msgDataTA.getText().split(",");
|
||||
data = ByteUtil.encodeDataList(lexaList);
|
||||
} else {
|
||||
data = new byte[]{};
|
||||
}
|
||||
|
||||
byte[] contractAddress = Hex.decode(contractAddrInput.getText());
|
||||
|
||||
Account account = ((AccountWrapper) creatorAddressCombo.getSelectedItem()).getAccount();
|
||||
|
||||
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
|
||||
|
||||
BigInteger nonce = account.getNonce();
|
||||
BigInteger gasPrice = new BigInteger("10000000000000");
|
||||
|
||||
BigInteger gasBI = new BigInteger(gasInput.getText());
|
||||
byte[] gasValue = BigIntegers.asUnsignedByteArray(gasBI);
|
||||
BigInteger endowment = new BigInteger("1000");
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Contract call:");
|
||||
logger.info("tx.nonce: {}", nonce == null ? "null" : nonce.toString());
|
||||
logger.info("tx.gasPrice: {}", Hex.toHexString(BigIntegers.asUnsignedByteArray(gasPrice)));
|
||||
logger.info("tx.gasValue: {}", Hex.toHexString(gasValue));
|
||||
logger.info("tx.address: {}", Hex.toHexString(contractAddress));
|
||||
logger.info("tx.endowment: {}", Hex.toHexString(BigIntegers.asUnsignedByteArray(endowment)));
|
||||
logger.info("tx.data: {}", Hex.toHexString(data));
|
||||
}
|
||||
|
||||
Transaction tx = UIEthereumManager.ethereum.createTransaction(
|
||||
nonce,
|
||||
gasPrice, gasBI,
|
||||
contractAddress, endowment, data);
|
||||
|
||||
try {
|
||||
tx.sign(senderPrivKey);
|
||||
} catch (Exception e1) {
|
||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||
return null;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
public class AccountWrapper {
|
||||
|
||||
private Account account;
|
||||
|
||||
public AccountWrapper(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String addressShort =
|
||||
Utils.getAddressShortString(account.getEcKey().getAddress());
|
||||
|
||||
String valueShort = "0";
|
||||
|
||||
String result = String.format(" By: [%s] %s", addressShort,
|
||||
valueShort);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private class JTableStorageModel extends DefaultTableModel {
|
||||
private JTableStorageModel(Map<String, String> data) {
|
||||
|
||||
if (data != null) {
|
||||
|
||||
this.setColumnCount(2);
|
||||
this.setRowCount(data.size());
|
||||
|
||||
int i = 0;
|
||||
for (String key : data.keySet()) {
|
||||
this.setValueAt(key, i, 0);
|
||||
this.setValueAt(data.get(key), i, 1);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
ContractCallDialog ccd = new ContractCallDialog(null);
|
||||
ccd.setVisible(true);
|
||||
ccd.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
ccd.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
UIEthereumManager.ethereum.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,358 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Account;
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.core.Wallet;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComboBoxUI;
|
||||
import javax.swing.plaf.basic.BasicComboPopup;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 18.05.14
|
||||
*/
|
||||
class ContractSubmitDialog extends JDialog implements MessageAwareDialog {
|
||||
|
||||
private static final long serialVersionUID = -3622984456084608996L;
|
||||
|
||||
ContractSubmitDialog dialog;
|
||||
JComboBox<AccountWrapper> creatorAddressCombo;
|
||||
final JTextField gasInput;
|
||||
final JTextField contractAddrInput;
|
||||
|
||||
private byte[] initByteCode;
|
||||
|
||||
|
||||
JLabel statusMsg = null;
|
||||
|
||||
public ContractSubmitDialog(Frame parent, byte[] byteCode) {
|
||||
super(parent, "Contract Details: ", false);
|
||||
dialog = this;
|
||||
this.initByteCode = byteCode;
|
||||
|
||||
contractAddrInput = new JTextField(5);
|
||||
GUIUtils.addStyle(contractAddrInput, "Contract Address: ");
|
||||
|
||||
contractAddrInput.setBounds(70, 30, 350, 45);
|
||||
this.getContentPane().add(contractAddrInput);
|
||||
|
||||
gasInput = new JTextField(5);
|
||||
GUIUtils.addStyle(gasInput, "Gas: ");
|
||||
|
||||
JTextArea contractDataTA = new JTextArea();
|
||||
contractDataTA.setLineWrap(true);
|
||||
JScrollPane contractDataInput = new JScrollPane(contractDataTA);
|
||||
GUIUtils.addStyle(contractDataTA, null, false);
|
||||
GUIUtils.addStyle(contractDataInput, "Code:");
|
||||
|
||||
String byteCodeText = GUIUtils.getHexStyledText(byteCode);
|
||||
contractDataTA.setText(byteCodeText);
|
||||
contractDataTA.setEditable(false);
|
||||
contractDataTA.setCaretPosition(0);
|
||||
|
||||
this.getContentPane().setBackground(Color.WHITE);
|
||||
this.getContentPane().setLayout(null);
|
||||
|
||||
|
||||
contractDataInput.setBounds(70, 80, 350, 165);
|
||||
this.getContentPane().add(contractDataInput);
|
||||
|
||||
gasInput.setBounds(330, 260, 90, 45);
|
||||
this.getContentPane().add(gasInput);
|
||||
|
||||
URL rejectIconURL = ClassLoader.getSystemResource("buttons/reject.png");
|
||||
ImageIcon rejectIcon = new ImageIcon(rejectIconURL);
|
||||
JLabel rejectLabel = new JLabel(rejectIcon);
|
||||
rejectLabel.setToolTipText("Cancel");
|
||||
rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
URL playIconURL = ClassLoader.getSystemResource("buttons/play.png");
|
||||
ImageIcon playIcon = new ImageIcon(playIconURL);
|
||||
JLabel playLabel = new JLabel(playIcon);
|
||||
playLabel.setToolTipText("Play Drafted");
|
||||
playLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
playLabel.setBounds(438, 100, 42, 42);
|
||||
this.getContentPane().add(playLabel);
|
||||
|
||||
playLabel.addMouseListener(
|
||||
new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
|
||||
Transaction tx = null;
|
||||
try {
|
||||
tx = createTransaction();
|
||||
} catch (Exception e1) {
|
||||
|
||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||
return;
|
||||
}
|
||||
contractAddrInput.setText(Hex.toHexString(tx.getContractAddress()));
|
||||
|
||||
Block lastBlock = UIEthereumManager.ethereum.getBlockchain().getBestBlock();
|
||||
ProgramPlayDialog.createAndShowGUI(tx.getData(), tx, lastBlock);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
JLabel statusMessage = new JLabel("");
|
||||
statusMessage.setBounds(50, 360, 400, 50);
|
||||
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.statusMsg = statusMessage;
|
||||
this.getContentPane().add(statusMessage);
|
||||
|
||||
rejectLabel.setBounds(260, 325, 45, 45);
|
||||
this.getContentPane().add(rejectLabel);
|
||||
rejectLabel.setVisible(true);
|
||||
rejectLabel.addMouseListener(
|
||||
new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
|
||||
dialog.dispose();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
URL approveIconURL = ClassLoader.getSystemResource("buttons/approve.png");
|
||||
ImageIcon approveIcon = new ImageIcon(approveIconURL);
|
||||
JLabel approveLabel = new JLabel(approveIcon);
|
||||
approveLabel.setToolTipText("Submit the transaction");
|
||||
approveLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
approveLabel.setBounds(200, 325, 45, 45);
|
||||
this.getContentPane().add(approveLabel);
|
||||
approveLabel.setVisible(true);
|
||||
|
||||
approveLabel.addMouseListener(
|
||||
new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
submitContract();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
gasInput.setText("1000");
|
||||
|
||||
JComboBox<AccountWrapper> creatorAddressCombo = new JComboBox<AccountWrapper>() {
|
||||
@Override
|
||||
public ComboBoxUI getUI() {
|
||||
return super.getUI();
|
||||
}
|
||||
};
|
||||
creatorAddressCombo.setOpaque(true);
|
||||
creatorAddressCombo.setEnabled(true);
|
||||
|
||||
creatorAddressCombo.setBackground(Color.WHITE);
|
||||
creatorAddressCombo.setFocusable(false);
|
||||
|
||||
this.creatorAddressCombo = creatorAddressCombo;
|
||||
|
||||
final Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
JComponent editor = (JComponent) (creatorAddressCombo.getEditor().getEditorComponent());
|
||||
editor.setForeground(Color.RED);
|
||||
|
||||
Wallet wallet = UIEthereumManager.ethereum.getWallet();
|
||||
Collection<Account> accounts = wallet.getAccountCollection();
|
||||
|
||||
for (Account account : accounts) {
|
||||
creatorAddressCombo.addItem(new AccountWrapper(account));
|
||||
}
|
||||
|
||||
creatorAddressCombo.setRenderer(new DefaultListCellRenderer() {
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
setBackground(Color.WHITE);
|
||||
setForeground(new Color(143, 170, 220));
|
||||
setFont(new Font("Monospaced", 0, 13));
|
||||
setBorder(BorderFactory.createEmptyBorder());
|
||||
super.paint(g);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
creatorAddressCombo.setPopupVisible(false);
|
||||
|
||||
Object child = creatorAddressCombo.getAccessibleContext().getAccessibleChild(0);
|
||||
BasicComboPopup popup = (BasicComboPopup) child;
|
||||
|
||||
JList list = popup.getList();
|
||||
list.setSelectionBackground(Color.cyan);
|
||||
list.setBorder(null);
|
||||
|
||||
for (int i = 0; i < creatorAddressCombo.getComponentCount(); i++) {
|
||||
if (creatorAddressCombo.getComponent(i) instanceof CellRendererPane) {
|
||||
CellRendererPane crp = ((CellRendererPane)
|
||||
(creatorAddressCombo.getComponent(i)));
|
||||
}
|
||||
if (creatorAddressCombo.getComponent(i) instanceof AbstractButton) {
|
||||
((AbstractButton) creatorAddressCombo.getComponent(i))
|
||||
.setBorder(line);
|
||||
}
|
||||
}
|
||||
creatorAddressCombo.setBounds(73, 267, 230, 36);
|
||||
this.getContentPane().add(creatorAddressCombo);
|
||||
this.getContentPane().revalidate();
|
||||
this.getContentPane().repaint();
|
||||
this.setResizable(false);
|
||||
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
protected JRootPane createRootPane() {
|
||||
|
||||
Container parent = this.getParent();
|
||||
|
||||
if (parent != null) {
|
||||
Dimension parentSize = parent.getSize();
|
||||
Point p = parent.getLocation();
|
||||
setLocation(p.x + parentSize.width / 4, p.y + 10);
|
||||
}
|
||||
|
||||
JRootPane rootPane = new JRootPane();
|
||||
KeyStroke stroke = KeyStroke.getKeyStroke("ESCAPE");
|
||||
Action actionListener = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
dispose();
|
||||
}
|
||||
};
|
||||
InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
inputMap.put(stroke, "ESCAPE");
|
||||
rootPane.getActionMap().put("ESCAPE", actionListener);
|
||||
|
||||
this.setSize(500, 430);
|
||||
return rootPane;
|
||||
}
|
||||
|
||||
public void infoStatusMsg(String text) {
|
||||
this.statusMsg.setForeground(Color.GREEN.darker().darker());
|
||||
this.statusMsg.setText(text);
|
||||
}
|
||||
|
||||
public void alertStatusMsg(String text) {
|
||||
this.statusMsg.setForeground(Color.RED);
|
||||
this.statusMsg.setText(text);
|
||||
}
|
||||
|
||||
public void submitContract() {
|
||||
|
||||
if (!validInput())
|
||||
return;
|
||||
|
||||
Transaction tx = null;
|
||||
try {
|
||||
tx = createTransaction();
|
||||
} catch (Exception e1) {
|
||||
|
||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||
return;
|
||||
}
|
||||
contractAddrInput.setText(Hex.toHexString(tx.getContractAddress()));
|
||||
|
||||
if (!UIEthereumManager.ethereum.isConnected()) {
|
||||
dialog.alertStatusMsg("Not connected to any peer");
|
||||
return;
|
||||
}
|
||||
|
||||
// SwingWorker
|
||||
DialogWorker worker = new DialogWorker(tx, this);
|
||||
worker.execute();
|
||||
}
|
||||
|
||||
private Transaction createTransaction() {
|
||||
|
||||
Account account = ((AccountWrapper) creatorAddressCombo.getSelectedItem()).getAccount();
|
||||
|
||||
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
|
||||
BigInteger nonce = UIEthereumManager.ethereum.getRepository().getNonce(account.getAddress());
|
||||
byte[] gasPrice = new BigInteger("10000000000000").toByteArray();
|
||||
|
||||
BigInteger gasBI = new BigInteger(gasInput.getText());
|
||||
byte[] gasValue = BigIntegers.asUnsignedByteArray(gasBI);
|
||||
byte[] endowment = BigIntegers.asUnsignedByteArray(new BigInteger("1000"));
|
||||
|
||||
byte[] zeroAddress = null;
|
||||
|
||||
// UIEthereumManager.ethereum.createTransaction();
|
||||
|
||||
Transaction tx = new Transaction(BigIntegers.asUnsignedByteArray(nonce),
|
||||
gasPrice, gasValue,
|
||||
zeroAddress, endowment, initByteCode);
|
||||
|
||||
tx.sign(senderPrivKey);
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
private boolean validInput() {
|
||||
|
||||
Account account = ((AccountWrapper) creatorAddressCombo.getSelectedItem()).getAccount();
|
||||
BigInteger currentBalance =
|
||||
UIEthereumManager.ethereum.getRepository().getBalance(account.getAddress());
|
||||
|
||||
BigInteger gasPrice = BigInteger.valueOf(42);
|
||||
BigInteger gasInput = new BigInteger(this.gasInput.getText());
|
||||
|
||||
boolean canAfford = currentBalance.compareTo(gasPrice.multiply(gasInput)) >= 0;
|
||||
|
||||
if (!canAfford) {
|
||||
alertStatusMsg("The address can't afford this transaction");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
AccountState as = new AccountState();
|
||||
ContractSubmitDialog pod = new ContractSubmitDialog(null, null);
|
||||
pod.setVisible(true);
|
||||
}
|
||||
|
||||
public class AccountWrapper {
|
||||
|
||||
private Account account;
|
||||
|
||||
public AccountWrapper(Account account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
String addressShort = Utils.getAddressShortString(account.getEcKey().getAddress());
|
||||
String valueShort = Utils.getValueShortString(
|
||||
UIEthereumManager.ethereum.getRepository().getBalance(account.getAddress())
|
||||
);
|
||||
|
||||
String result = String.format(" By: [%s] %s", addressShort, valueShort);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Transaction;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 26.05.2014
|
||||
*/
|
||||
public class DialogWorker extends SwingWorker<Transaction, Object> {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(DialogWorker.class);
|
||||
|
||||
private Transaction tx;
|
||||
private MessageAwareDialog dialog;
|
||||
|
||||
public DialogWorker(Transaction tx, MessageAwareDialog dialog) {
|
||||
this.tx = tx;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Transaction doInBackground() throws Exception {
|
||||
|
||||
Future<Transaction> future = UIEthereumManager.ethereum.submitTransaction(tx);
|
||||
dialog.infoStatusMsg("Transaction sent to the network, waiting for approve");
|
||||
|
||||
try {
|
||||
future.get(CONFIG.transactionApproveTimeout(), TimeUnit.SECONDS);
|
||||
} catch (TimeoutException toe) {
|
||||
logger.error(toe.getMessage(), toe);
|
||||
dialog.alertStatusMsg("Transaction wasn't approved, network timeout");
|
||||
return null;
|
||||
} catch (InterruptedException ie) {
|
||||
logger.error(ie.getMessage(), ie);
|
||||
dialog.alertStatusMsg("Transaction wasn't approved");
|
||||
return null;
|
||||
} catch (ExecutionException ee) {
|
||||
logger.error(ee.getMessage(), ee);
|
||||
dialog.alertStatusMsg("Transaction wasn't approved");
|
||||
return null;
|
||||
} finally {
|
||||
future.cancel(true);
|
||||
}
|
||||
|
||||
dialog.infoStatusMsg("Transaction got approved");
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.serpent.SerpentCompiler;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 23.05.2014
|
||||
*/
|
||||
public class GUIUtils {
|
||||
|
||||
public static void addStyle(JTextField textField, String labelName) {
|
||||
textField.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
TitledBorder titled = BorderFactory.createTitledBorder(line, labelName);
|
||||
titled.setTitleFont(new Font("Verdana", 0, 13));
|
||||
titled.setTitleColor(new Color(213, 225, 185));
|
||||
Border empty = new EmptyBorder(5, 8, 5, 8);
|
||||
CompoundBorder border = new CompoundBorder(titled, empty);
|
||||
textField.setBorder(border);
|
||||
textField.setForeground(new Color(143, 170, 220));
|
||||
textField.setFont(new Font("Monospaced", 0, 13));
|
||||
}
|
||||
|
||||
public static void addStyle(JTextArea textArea, String labelName, boolean isBorder) {
|
||||
|
||||
Border border = null;
|
||||
if (isBorder) {
|
||||
Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
TitledBorder titled = BorderFactory.createTitledBorder(line, labelName);
|
||||
titled.setTitleFont(new Font("Verdana", 0, 13));
|
||||
titled.setTitleColor(new Color(213, 225, 185));
|
||||
Border empty = new EmptyBorder(5, 8, 5, 8);
|
||||
CompoundBorder cBorder = new CompoundBorder(titled, empty);
|
||||
}
|
||||
textArea.setBorder(border);
|
||||
textArea.setForeground(new Color(143, 170, 220));
|
||||
textArea.setFont(new Font("Monospaced", 0, 13));
|
||||
}
|
||||
|
||||
public static void addStyle(JScrollPane jScrollPane, String labelName) {
|
||||
Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
TitledBorder titled = BorderFactory.createTitledBorder(line, labelName);
|
||||
titled.setTitleFont(new Font("Verdana", 0, 13));
|
||||
titled.setTitleColor(new Color(213, 225, 185));
|
||||
Border empty = new EmptyBorder(5, 8, 5, 8);
|
||||
CompoundBorder border = new CompoundBorder(titled, empty);
|
||||
jScrollPane.setBorder(border);
|
||||
jScrollPane.setForeground(new Color(143, 170, 220));
|
||||
jScrollPane.setBackground(Color.WHITE);
|
||||
jScrollPane.setFont(new Font("Monospaced", 0, 13));
|
||||
jScrollPane.setHorizontalScrollBar(null);
|
||||
}
|
||||
|
||||
public static void addStyle(JTable jTable) {
|
||||
jTable.setForeground(new Color(143, 170, 220));
|
||||
jTable.setBackground(Color.WHITE);
|
||||
jTable.setFont(new Font("Monospaced", 0, 13));
|
||||
}
|
||||
|
||||
public static String getHexStyledText(byte[] data) {
|
||||
String[] dataHex = Hex.toHexString(data).split("(?<=\\G.{2})");
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < dataHex.length; ++i) {
|
||||
sb.append(dataHex[i]).append(" ");
|
||||
if ((i + 1) % 8 == 0 && i != 0) sb.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String getStyledAsmCode(String asmCode) {
|
||||
|
||||
String initBlock = SerpentCompiler.extractInitBlock(asmCode);
|
||||
String codeBlock = SerpentCompiler.extractCodeBlock(asmCode);
|
||||
|
||||
return String.format(" \n\n *** [Init] *** \n\n %s \n" +
|
||||
"\n *** [Code] *** \n\n %s \n\n", initBlock, codeBlock);
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
/**
|
||||
* This interface describes the methods required
|
||||
* for any dialog that displays info- and alert status messages.
|
||||
*/
|
||||
public interface MessageAwareDialog {
|
||||
|
||||
public void infoStatusMsg(final String text);
|
||||
|
||||
public void alertStatusMsg(final String text);
|
||||
}
|
|
@ -1,271 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Account;
|
||||
import org.ethereum.core.Transaction;
|
||||
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 18.05.14
|
||||
*/
|
||||
class PayOutDialog extends JDialog implements MessageAwareDialog {
|
||||
|
||||
private static final long serialVersionUID = -2838121935782110981L;
|
||||
|
||||
private PayOutDialog dialog;
|
||||
|
||||
private Account account = null;
|
||||
private JLabel statusMsg = null;
|
||||
|
||||
private final JTextField receiverInput;
|
||||
private final JTextField amountInput;
|
||||
private final JTextField feeInput;
|
||||
|
||||
public PayOutDialog(Frame parent, final Account account) {
|
||||
super(parent, "Payout details: ", false);
|
||||
dialog = this;
|
||||
|
||||
this.account = account;
|
||||
|
||||
receiverInput = new JTextField(18);
|
||||
GUIUtils.addStyle(receiverInput, "Pay to:");
|
||||
|
||||
amountInput = new JTextField(18);
|
||||
GUIUtils.addStyle(amountInput, "Amount: ");
|
||||
|
||||
feeInput = new JTextField(5);
|
||||
GUIUtils.addStyle(feeInput, "Fee: ");
|
||||
|
||||
this.getContentPane().setBackground(Color.WHITE);
|
||||
this.getContentPane().setLayout(null);
|
||||
|
||||
receiverInput.setBounds(70, 30, 350, 45);
|
||||
this.getContentPane().add(receiverInput);
|
||||
|
||||
amountInput.setBounds(70, 80, 250, 45);
|
||||
this.getContentPane().add(amountInput);
|
||||
|
||||
feeInput.setBounds(330, 80, 90, 45);
|
||||
this.getContentPane().add(feeInput);
|
||||
|
||||
URL rejectIconURL = ClassLoader.getSystemResource("buttons/reject.png");
|
||||
ImageIcon rejectIcon = new ImageIcon(rejectIconURL);
|
||||
JLabel rejectLabel = new JLabel(rejectIcon);
|
||||
rejectLabel.setToolTipText("Cancel");
|
||||
rejectLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
JLabel statusMessage = new JLabel("");
|
||||
statusMessage.setBounds(50, 180, 400, 50);
|
||||
statusMessage.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
this.statusMsg = statusMessage;
|
||||
this.getContentPane().add(statusMessage);
|
||||
|
||||
rejectLabel.setBounds(260, 145, 45, 45);
|
||||
this.getContentPane().add(rejectLabel);
|
||||
rejectLabel.setVisible(true);
|
||||
rejectLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
dialog.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
URL approveIconURL = ClassLoader.getSystemResource("buttons/approve.png");
|
||||
ImageIcon approveIcon = new ImageIcon(approveIconURL);
|
||||
JLabel approveLabel = new JLabel(approveIcon);
|
||||
approveLabel.setToolTipText("Submit the transaction");
|
||||
approveLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
|
||||
approveLabel.setBounds(200, 145, 45, 45);
|
||||
this.getContentPane().add(approveLabel);
|
||||
approveLabel.setVisible(true);
|
||||
|
||||
approveLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
|
||||
if (!validInput()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BigInteger fee = new BigInteger(feeInput.getText());
|
||||
BigInteger value = new BigInteger(amountInput.getText());
|
||||
byte[] address = Hex.decode(receiverInput.getText());
|
||||
|
||||
|
||||
if (!UIEthereumManager.ethereum.isConnected()) {
|
||||
dialog.alertStatusMsg("Not connected to any peer");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
byte[] senderPrivKey = account.getEcKey().getPrivKeyBytes();
|
||||
|
||||
BigInteger nonce = account.getNonce();
|
||||
|
||||
byte[] gasPrice = BigInteger.valueOf(42).toByteArray();
|
||||
|
||||
Transaction tx = new Transaction(
|
||||
BigIntegers.asUnsignedByteArray(nonce),
|
||||
gasPrice,
|
||||
BigIntegers.asUnsignedByteArray(fee), address,
|
||||
BigIntegers.asUnsignedByteArray(value), null);
|
||||
|
||||
try {
|
||||
tx.sign(senderPrivKey);
|
||||
} catch (Exception e1) {
|
||||
dialog.alertStatusMsg("Failed to sign the transaction");
|
||||
return;
|
||||
}
|
||||
|
||||
// SwingWorker
|
||||
DialogWorker worker = new DialogWorker(tx, dialog);
|
||||
worker.execute();
|
||||
}
|
||||
});
|
||||
|
||||
feeInput.setText("1000");
|
||||
amountInput.setText("0");
|
||||
|
||||
this.getContentPane().revalidate();
|
||||
this.getContentPane().repaint();
|
||||
this.setResizable(false);
|
||||
}
|
||||
|
||||
private boolean validInput() {
|
||||
|
||||
if (UIEthereumManager.ethereum.isBlockchainLoading()) {
|
||||
alertStatusMsg("No transaction is allowed during block chain downloading.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
String receiverText = receiverInput.getText();
|
||||
if (receiverText == null || receiverText.isEmpty()) {
|
||||
alertStatusMsg("Should specify valid receiver address");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Pattern.matches("[0-9a-fA-F]+", receiverText)) {
|
||||
alertStatusMsg("Should specify valid receiver address");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Hex.decode(receiverText).length != 20) {
|
||||
alertStatusMsg("Should specify valid receiver address");
|
||||
return false;
|
||||
}
|
||||
|
||||
String amountText = amountInput.getText();
|
||||
if (amountText == null || amountText.isEmpty()) {
|
||||
alertStatusMsg("Should specify amount to transfer");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Pattern.matches("[0-9]+", amountText)) {
|
||||
alertStatusMsg("Should specify numeric value for amount ");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amountText.equals("0")) {
|
||||
alertStatusMsg("Should specify more than zero for transaction");
|
||||
return false;
|
||||
}
|
||||
|
||||
String feeText = feeInput.getText();
|
||||
if (feeText == null || feeText.isEmpty()) {
|
||||
alertStatusMsg("Should specify fee to fund the transaction");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Pattern.matches("[0-9]+", feeText)) {
|
||||
alertStatusMsg("Should specify numeric value for a fee");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// check if the tx is affordable
|
||||
BigInteger ammountValue = new BigInteger(amountText);
|
||||
BigInteger feeValue = new BigInteger(feeText);
|
||||
BigInteger gasPrice = BigInteger.valueOf(42);
|
||||
BigInteger currentBalance = account.getBalance();
|
||||
|
||||
boolean canAfford = gasPrice.multiply(feeValue).add(ammountValue).compareTo(currentBalance) != 1;
|
||||
|
||||
if (!canAfford) {
|
||||
alertStatusMsg("The address can't afford this transaction");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected JRootPane createRootPane() {
|
||||
|
||||
Container parent = this.getParent();
|
||||
|
||||
if (parent != null) {
|
||||
Dimension parentSize = parent.getSize();
|
||||
Point p = parent.getLocation();
|
||||
setLocation(p.x + parentSize.width / 4, p.y + parentSize.height / 4);
|
||||
}
|
||||
|
||||
JRootPane rootPane = new JRootPane();
|
||||
KeyStroke stroke = KeyStroke.getKeyStroke("ESCAPE");
|
||||
Action actionListener = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
dispose();
|
||||
}
|
||||
};
|
||||
InputMap inputMap = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
inputMap.put(stroke, "ESCAPE");
|
||||
rootPane.getActionMap().put("ESCAPE", actionListener);
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
setSize(500, 255);
|
||||
setVisible(true);
|
||||
});
|
||||
|
||||
|
||||
return rootPane;
|
||||
}
|
||||
|
||||
public void infoStatusMsg(final String text) {
|
||||
|
||||
final PayOutDialog dialog = this;
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
dialog.statusMsg.setForeground(Color.GREEN.darker().darker());
|
||||
dialog.statusMsg.setText(text);
|
||||
dialog.revalidate();
|
||||
dialog.repaint();
|
||||
});
|
||||
}
|
||||
|
||||
public void alertStatusMsg(final String text) {
|
||||
final PayOutDialog dialog = this;
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
dialog.statusMsg.setForeground(Color.RED);
|
||||
dialog.statusMsg.setText(text);
|
||||
dialog.revalidate();
|
||||
dialog.repaint();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* A simple example showing how to modify the fonts and colors used in an
|
||||
* RSyntaxTextArea. There are two methods to do this - via the Java API, and via
|
||||
* an XML file. The latter method is preferred since it's more modular, and
|
||||
* provides a way for your users to customize RSTA in your application.<p>
|
||||
*
|
||||
* This example uses RSyntaxTextArea 2.0.1.<p>
|
||||
*
|
||||
* Project Home: http://fifesoft.com/rsyntaxtextarea<br>
|
||||
* Downloads: https://sourceforge.net/projects/rsyntaxtextarea
|
||||
*/
|
||||
public class PeerInfoWindow extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private boolean autoScroll = false;
|
||||
private RSyntaxTextArea textArea;
|
||||
private ToolBar toolBar = null;
|
||||
|
||||
/**
|
||||
* ERROR (exceptions) WARN (when something happens that's not supposed to)
|
||||
* INFO (wire output)
|
||||
* DEBUG (test/displaying intermediate values),
|
||||
* TRACE (start/end method)
|
||||
*/
|
||||
public PeerInfoWindow(PeersTableModel.PeerInfo peerInfo) {
|
||||
final PeerInfoWindow thisConsole = this;
|
||||
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
addCloseAction();
|
||||
|
||||
JPanel cp = new JPanel(new BorderLayout());
|
||||
|
||||
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance();
|
||||
atmf.putMapping("text/console", "org.ethereum.gui.ConsoleTokenMaker");
|
||||
|
||||
textArea = new RSyntaxTextArea(16, 44);
|
||||
textArea.setSyntaxEditingStyle("text/console");
|
||||
// textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_LISP);
|
||||
textArea.setCodeFoldingEnabled(true);
|
||||
textArea.setAntiAliasingEnabled(true);
|
||||
|
||||
RTextScrollPane sp = new RTextScrollPane(textArea);
|
||||
textArea.setText(peerInfo.toString());
|
||||
|
||||
cp.add(sp);
|
||||
|
||||
setContentPane(cp);
|
||||
setTitle("Connection Console");
|
||||
// setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
pack();
|
||||
setLocation(802, 460);
|
||||
|
||||
if (CONFIG.peerDiscovery())
|
||||
UIEthereumManager.ethereum.startPeerDiscovery();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Start all Swing applications on the EDT.
|
||||
SwingUtilities.invokeLater(() -> new PeerInfoWindow(null).setVisible(true));
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.geo.IpGeoDB;
|
||||
import org.ethereum.net.eth.StatusMessage;
|
||||
import org.ethereum.net.p2p.HelloMessage;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import com.maxmind.geoip.Location;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 25.04.14
|
||||
*/
|
||||
public class PeersTableModel extends AbstractTableModel {
|
||||
|
||||
private List<PeerInfo> peerInfoList = new ArrayList<>();
|
||||
Timer updater = new Timer();
|
||||
|
||||
public PeersTableModel() {
|
||||
updater.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
SwingUtilities.invokeLater(
|
||||
PeersTableModel.this::updateModel
|
||||
);
|
||||
}
|
||||
}, 0, 100);
|
||||
}
|
||||
|
||||
public String getColumnName(int column) {
|
||||
if (column == 0) return "Location";
|
||||
if (column == 1) return "IP";
|
||||
if (column == 2) return "Environment";
|
||||
if (column == 3) return "Live";
|
||||
else return "";
|
||||
}
|
||||
|
||||
public boolean isCellEditable(int row, int column) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Class<?> getColumnClass(int column) {
|
||||
if (column == 0) return ImageIcon.class;
|
||||
if (column == 1) return String.class;
|
||||
if (column == 2) return String.class;
|
||||
if (column == 3) return ImageIcon.class;
|
||||
else return String.class;
|
||||
}
|
||||
|
||||
public Object getValueAt(int row, int column) {
|
||||
|
||||
PeerInfo peerInfo = peerInfoList.get(row);
|
||||
|
||||
if (column == 0) {
|
||||
String countryCode = peerInfo.getLocation().countryCode;
|
||||
|
||||
ImageIcon flagIcon = null;
|
||||
if (countryCode != null) {
|
||||
URL flagURL = ClassLoader.getSystemResource("flags/" + countryCode.toLowerCase() + ".png");
|
||||
flagIcon = new ImageIcon(flagURL);
|
||||
}
|
||||
return flagIcon;
|
||||
}
|
||||
if (column == 1)
|
||||
return peerInfo.getIp().getHostAddress();
|
||||
|
||||
if (column == 2) {
|
||||
|
||||
if (peerInfo.getLastAccessed() == 0)
|
||||
return "?";
|
||||
else
|
||||
return (System.currentTimeMillis() - peerInfo.getLastAccessed()) / 1000 + " seconds ago";
|
||||
}
|
||||
|
||||
if (column == 3) {
|
||||
|
||||
ImageIcon flagIcon = null;
|
||||
if (peerInfo.isConnected()) {
|
||||
flagIcon = Utils.getImageIcon("connected.png");
|
||||
} else {
|
||||
flagIcon = Utils.getImageIcon("disconnected.png");
|
||||
}
|
||||
return flagIcon;
|
||||
} else return "";
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return this.peerInfoList.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
public void updateModel() {
|
||||
synchronized (peerInfoList) {
|
||||
peerInfoList.clear();
|
||||
|
||||
final Set<org.ethereum.net.peerdiscovery.PeerInfo> peers = UIEthereumManager.ethereum.getPeers();
|
||||
|
||||
synchronized (peers) {
|
||||
|
||||
for (org.ethereum.net.peerdiscovery.PeerInfo peer : peers) {
|
||||
InetAddress addr = peer.getAddress();
|
||||
Location cr = IpGeoDB.getLocationForIp(addr);
|
||||
peerInfoList.add(new PeerInfo(cr, addr, peer.isOnline(), peer.getLastCheckTime(),
|
||||
peer.getHandshakeHelloMessage(), peer.getStatusMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PeerInfo getPeerInfo(int index) {
|
||||
return peerInfoList.get(index);
|
||||
}
|
||||
|
||||
|
||||
public class PeerInfo {
|
||||
|
||||
Location location;
|
||||
InetAddress ip;
|
||||
boolean connected;
|
||||
long lastAccessed = 0;
|
||||
|
||||
HelloMessage handshakeHelloMessage;
|
||||
StatusMessage handshakeStatusMessage;
|
||||
|
||||
private PeerInfo(Location location, InetAddress ip,
|
||||
boolean isConnected, long lastAccessed, HelloMessage helloMessage, StatusMessage
|
||||
statusMessage) {
|
||||
|
||||
if (location == null)
|
||||
this.location = new Location();
|
||||
else
|
||||
this.location = location;
|
||||
|
||||
this.ip = ip;
|
||||
this.connected = isConnected;
|
||||
this.lastAccessed = lastAccessed;
|
||||
this.handshakeHelloMessage = helloMessage;
|
||||
this.handshakeStatusMessage = statusMessage;
|
||||
}
|
||||
|
||||
private Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
private InetAddress getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
private boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
public long getLastAccessed() {
|
||||
return lastAccessed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PeerInfo{" +
|
||||
"location=" + location.countryName +
|
||||
", geo= [ " + location.latitude + "/" + location.longitude + " ]" +
|
||||
", ip=" + ip +
|
||||
", connected=" + connected +
|
||||
", lastAccessed=" + lastAccessed +
|
||||
'}' + "\n -->" + (handshakeHelloMessage == null ? "" : handshakeHelloMessage.toString())
|
||||
+ "\n -->" + (handshakeStatusMessage == null ? "" : handshakeStatusMessage.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 25.04.14
|
||||
*/
|
||||
public class PeersTableWindow extends JFrame {
|
||||
|
||||
// Instance attributes used in this example
|
||||
private JPanel topPanel;
|
||||
private JTable table;
|
||||
private JScrollPane scrollPane;
|
||||
private Timer updater = new Timer();
|
||||
|
||||
private ToolBar toolBar;
|
||||
|
||||
// Constructor of main frame
|
||||
public PeersTableWindow(ToolBar toolBar) {
|
||||
|
||||
this.toolBar = toolBar;
|
||||
addCloseAction();
|
||||
|
||||
// Set the frame characteristics
|
||||
setTitle("Ethereum Peers");
|
||||
setSize(515, 400);
|
||||
setLocation(615, 30);
|
||||
|
||||
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();
|
||||
topPanel.setLayout(new BorderLayout());
|
||||
topPanel.setBackground(Color.WHITE);
|
||||
|
||||
getContentPane().add(topPanel);
|
||||
getContentPane().setBackground(Color.WHITE);
|
||||
|
||||
// Create a new table instance
|
||||
table = new JTable();
|
||||
table.setModel(new PeersTableModel());
|
||||
|
||||
table.addMouseListener(new MouseAdapter() {
|
||||
public void mousePressed(MouseEvent me) {
|
||||
JTable table = (JTable) me.getSource();
|
||||
Point p = me.getPoint();
|
||||
int row = table.rowAtPoint(p);
|
||||
PeersTableModel model = (PeersTableModel) table.getModel();
|
||||
if (me.getClickCount() == 2) {
|
||||
final PeersTableModel.PeerInfo peerInfo = model.getPeerInfo(row);
|
||||
SwingUtilities.invokeLater(() -> new PeerInfoWindow(peerInfo).setVisible(true));
|
||||
System.out.println(peerInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
table.setFont(new Font("Courier New", Font.PLAIN, 15));
|
||||
table.setForeground(Color.GRAY);
|
||||
table.setTableHeader(null);
|
||||
|
||||
TableCellRenderer tcr = table.getDefaultRenderer(String.class);
|
||||
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) tcr;
|
||||
renderer.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
|
||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
table.setCellSelectionEnabled(true);
|
||||
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
table.getColumnModel().getColumn(0).setPreferredWidth(60);
|
||||
table.getColumnModel().getColumn(1).setPreferredWidth(200);
|
||||
table.getColumnModel().getColumn(2).setPreferredWidth(160);
|
||||
table.getColumnModel().getColumn(3).setPreferredWidth(60);
|
||||
|
||||
table.setRowMargin(3);
|
||||
table.setRowHeight(50);
|
||||
|
||||
table.setShowHorizontalLines(true);
|
||||
table.setShowVerticalLines(true);
|
||||
table.setGridColor(new Color(230, 230, 230));
|
||||
|
||||
// Add the table to a scrolling pane
|
||||
scrollPane = new JScrollPane(table);
|
||||
scrollPane.getViewport().setBackground(Color.WHITE);
|
||||
|
||||
topPanel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
updater.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
table.revalidate();
|
||||
table.repaint();
|
||||
}
|
||||
}, 1000, 1000);
|
||||
|
||||
UIEthereumManager.ethereum.startPeerDiscovery();
|
||||
}
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
toolBar.peersToggle.setSelected(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
PeersTableWindow mainFrame = new PeersTableWindow(null);
|
||||
mainFrame.setVisible(true);
|
||||
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
}
|
|
@ -1,195 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.vm.Program;
|
||||
import org.ethereum.vm.ProgramInvoke;
|
||||
import org.ethereum.vm.ProgramInvokeMockImpl;
|
||||
import org.ethereum.vm.VM;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 02.06.2014
|
||||
*/
|
||||
public class ProgramPlayDialog extends JPanel implements ActionListener,
|
||||
ChangeListener, Program.ProgramListener {
|
||||
|
||||
private List<String> outputList;
|
||||
private JTextArea console;
|
||||
private JSlider stepSlider;
|
||||
|
||||
private ProgramInvoke pi;
|
||||
|
||||
public ProgramPlayDialog(byte[] code) {
|
||||
this(code, new ProgramInvokeMockImpl());
|
||||
}
|
||||
|
||||
public ProgramPlayDialog(byte[] code, Transaction tx, Block lastBlock) {
|
||||
// this(code, ProgramInvokeFactory.createProgramInvoke(tx, lastBlock,
|
||||
// UIEthereumManager.ethereum.getRepository()));
|
||||
}
|
||||
|
||||
public ProgramPlayDialog(byte[] code, ProgramInvoke programInvoke) {
|
||||
pi = programInvoke;
|
||||
|
||||
outputList = new ArrayList<>();
|
||||
VM vm = new VM();
|
||||
|
||||
Program program = new Program(code, programInvoke);
|
||||
program.addListener(this);
|
||||
program.fullTrace();
|
||||
vm.play(program);
|
||||
|
||||
if (programInvoke.getRepository() != null)
|
||||
programInvoke.getRepository().rollback();
|
||||
|
||||
doGUI();
|
||||
}
|
||||
|
||||
public void doGUI() {
|
||||
|
||||
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
|
||||
|
||||
//Create the slider.
|
||||
stepSlider = new JSlider(JSlider.HORIZONTAL,
|
||||
0, outputList.size() - 1, 0);
|
||||
|
||||
stepSlider.addChangeListener(this);
|
||||
|
||||
//Turn on labels at major tick marks.
|
||||
|
||||
stepSlider.setMajorTickSpacing(1);
|
||||
if (outputList.size() > 40)
|
||||
stepSlider.setMajorTickSpacing(3);
|
||||
if (outputList.size() > 100)
|
||||
stepSlider.setMajorTickSpacing(20);
|
||||
|
||||
stepSlider.setMinorTickSpacing(1);
|
||||
stepSlider.setPaintTicks(true);
|
||||
stepSlider.setPaintLabels(true);
|
||||
stepSlider.setBorder(
|
||||
BorderFactory.createEmptyBorder(0, 0, 10, 0));
|
||||
Font font = new Font("Courier New", Font.PLAIN, 10);
|
||||
stepSlider.setFont(font);
|
||||
stepSlider.addChangeListener(this);
|
||||
|
||||
//Create the label that displays the animation.
|
||||
|
||||
int i = stepSlider.getValue();
|
||||
console = new JTextArea(outputList.get(i));
|
||||
console.setFont(new Font("Courier New", Font.PLAIN, 13));
|
||||
console.setForeground(new Color(183, 209, 253));
|
||||
console.setBackground(Color.BLACK);
|
||||
console.setLineWrap(true);
|
||||
|
||||
stepSlider.setFocusable(true);
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(console,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
|
||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scrollPane.getVerticalScrollBar().setPreferredSize(new Dimension(10, 0));
|
||||
|
||||
add(scrollPane);
|
||||
add(stepSlider);
|
||||
}
|
||||
|
||||
public void setFocus() {
|
||||
stepSlider.requestFocus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
JSlider source = (JSlider) e.getSource();
|
||||
int step = source.getValue();
|
||||
|
||||
int i = source.getValue();
|
||||
String out = outputList.get(i);
|
||||
|
||||
console.setText(out);
|
||||
console.setCaretPosition(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the GUI and show it. For thread safety,
|
||||
* this method should be invoked from the
|
||||
* event-dispatching thread.
|
||||
*/
|
||||
public static void createAndShowGUI(byte[] runCode, final Transaction tx, Block lastBlock) {
|
||||
|
||||
final ProgramPlayDialog ppd;
|
||||
if (tx != null)
|
||||
ppd = new ProgramPlayDialog(runCode, tx, lastBlock);
|
||||
else {
|
||||
ppd = new ProgramPlayDialog(runCode);
|
||||
}
|
||||
|
||||
//Create and set up the window.
|
||||
JFrame frame = new JFrame("Program Draft Play");
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
frame.setIconImage(img);
|
||||
|
||||
frame.setPreferredSize(new Dimension(580, 500));
|
||||
frame.setLocation(400, 200);
|
||||
|
||||
//Add content to the window.
|
||||
frame.add(ppd, BorderLayout.CENTER);
|
||||
|
||||
// close event
|
||||
frame.addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
|
||||
if (tx == null) {
|
||||
ppd.pi.getRepository().close();
|
||||
ppd.pi = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//Display the window.
|
||||
frame.pack();
|
||||
frame.setVisible(true);
|
||||
ppd.setFocus();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void output(String out) {
|
||||
outputList.add(out);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
/* Turn off metal's use of bold fonts */
|
||||
UIManager.put("swing.boldMetal", Boolean.FALSE);
|
||||
|
||||
//Schedule a job for the event-dispatching thread:
|
||||
//creating and showing this application's GUI.
|
||||
|
||||
String asmCode = "11 0 MSTORE 22 32 MSTORE 33 64 MSTORE 44 96 MSTORE 55 128 MSTORE 66 160 MSTORE 192 0 RETURN";
|
||||
// final byte[] code = SerpentCompiler.compileAssemblyToMachine(asmCode);
|
||||
|
||||
final byte[] code = Hex.decode("7f4e616d65526567000000000000000000000000000000000000000000000000003057307f4e616d6552656700000000000000000000000000000000000000000000000000573360455760415160566000396000f20036602259604556330e0f600f5933ff33560f601e5960003356576000335700604158600035560f602b590033560f60365960003356573360003557600035335700");
|
||||
SwingUtilities.invokeLater(() -> createAndShowGUI(code, null, null));
|
||||
}
|
||||
}
|
|
@ -1,478 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.serpent.SerpentCompiler;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
|
||||
import org.fife.ui.rsyntaxtextarea.SyntaxScheme;
|
||||
import org.fife.ui.rsyntaxtextarea.Token;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMakerFactory;
|
||||
import org.fife.ui.rtextarea.RTextScrollPane;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 24.04.14
|
||||
*/
|
||||
public class SerpentEditor extends JFrame {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("gui");
|
||||
|
||||
private String codeSample = "\n\n\n" +
|
||||
"" +
|
||||
"if !contract.storage[msg.data[0]]:\n" +
|
||||
" contract.storage[msg.data[0]] = msg.data[1]\n" +
|
||||
" return(1)\n" +
|
||||
"else:\n" +
|
||||
" return(0)\n";
|
||||
|
||||
private String codeSample2 = "\n\n\n" +
|
||||
"" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"a=block.gaslimit\n" +
|
||||
"b = block.difficulty\n" +
|
||||
"if 10*2+5 > 15:\n" +
|
||||
" b = 2\n" +
|
||||
"elif 2*6+5 < a ^ 6:\n" +
|
||||
" c = 4\n" +
|
||||
"else:\n" +
|
||||
" d = 5\n" +
|
||||
" \n" +
|
||||
"\n" +
|
||||
"return(0)\n";
|
||||
|
||||
private String defaultCode = "\n" +
|
||||
"\n" +
|
||||
"init: \n" +
|
||||
"\n" +
|
||||
" // [init block] - executed once when contract\n" +
|
||||
" // being initialized.\n" +
|
||||
" contract.storage[999] = 3 \n" +
|
||||
"\n" +
|
||||
"code:\n" +
|
||||
"\n" +
|
||||
" // [code block] - the actual code\n" +
|
||||
" // executed when the call msg\n" +
|
||||
" // hit the peer\n" +
|
||||
" a = contract.storage[999]\n" +
|
||||
" b = msg.data[a]\n";
|
||||
|
||||
private final RSyntaxTextArea codeArea;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final JSplitPane splitPanel;
|
||||
private final JTextArea result;
|
||||
private final JPanel contentPane;
|
||||
private JFileChooser fileChooser = null;
|
||||
|
||||
private ToolBar toolBar = null;
|
||||
|
||||
public SerpentEditor(ToolBar toolBar) {
|
||||
|
||||
this.toolBar = toolBar;
|
||||
addCloseAction();
|
||||
contentPane = new JPanel(new BorderLayout());
|
||||
|
||||
URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
this.setLocation(30, 70);
|
||||
|
||||
AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory) TokenMakerFactory.getDefaultInstance();
|
||||
atmf.putMapping("text/serpent", "org.ethereum.gui.SerpentTokenMaker");
|
||||
|
||||
codeArea = new RSyntaxTextArea(32, 80);
|
||||
codeArea.setSyntaxEditingStyle("text/serpent");
|
||||
codeArea.setCodeFoldingEnabled(true);
|
||||
codeArea.setAntiAliasingEnabled(true);
|
||||
codeArea.setText(defaultCode);
|
||||
|
||||
changeStyleProgrammatically();
|
||||
|
||||
RTextScrollPane sp = new RTextScrollPane(codeArea);
|
||||
|
||||
sp.setFoldIndicatorEnabled(true);
|
||||
contentPane.setLayout(new BorderLayout());
|
||||
|
||||
splitPanel = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
|
||||
splitPanel.setOneTouchExpandable(true);
|
||||
splitPanel.setDividerSize(5);
|
||||
splitPanel.setContinuousLayout(true);
|
||||
|
||||
contentPane.add(splitPanel, BorderLayout.CENTER);
|
||||
splitPanel.add(sp);
|
||||
|
||||
result = new JTextArea();
|
||||
result.setLineWrap(true);
|
||||
result.setWrapStyleWord(true);
|
||||
result.setVisible(false);
|
||||
|
||||
splitPanel.add(result);
|
||||
|
||||
JPanel controlsPanel = new JPanel();
|
||||
FlowLayout fl = new FlowLayout(FlowLayout.CENTER, 10, 5);
|
||||
// fl.setAlignment(FlowLayout.RIGHT);
|
||||
controlsPanel.setLayout(fl);
|
||||
controlsPanel.setMaximumSize(new Dimension(10000, 20));
|
||||
controlsPanel.setPreferredSize(new Dimension(600, 20));
|
||||
controlsPanel.setMinimumSize(new Dimension(1, 20));
|
||||
|
||||
contentPane.add(controlsPanel, BorderLayout.SOUTH);
|
||||
|
||||
createToolBar();
|
||||
|
||||
setContentPane(contentPane);
|
||||
setTitle("Serpent Editor");
|
||||
|
||||
pack();
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
private void changeStyleProgrammatically() {
|
||||
|
||||
// Set the font for all token types.
|
||||
|
||||
// Change a few things here and there.
|
||||
SyntaxScheme scheme = codeArea.getSyntaxScheme();
|
||||
|
||||
scheme.getStyle(Token.RESERVED_WORD).background = Color.white;
|
||||
scheme.getStyle(Token.RESERVED_WORD).foreground = Color.BLUE.darker();
|
||||
|
||||
scheme.getStyle(Token.IDENTIFIER).foreground = Color.black;
|
||||
|
||||
scheme.getStyle(Token.RESERVED_WORD_2).background = Color.WHITE;
|
||||
scheme.getStyle(Token.RESERVED_WORD_2).foreground = Color.MAGENTA.darker();
|
||||
|
||||
scheme.getStyle(Token.ANNOTATION).foreground = Color.ORANGE;
|
||||
scheme.getStyle(Token.ANNOTATION).background = Color.black;
|
||||
scheme.getStyle(Token.ANNOTATION).font = new Font("Consolas", Font.BOLD, 15);
|
||||
|
||||
// scheme.getStyle(Token.LITERAL_STRING_DOUBLE_QUOTE).underline = true;
|
||||
// scheme.getStyle(Token.LITERAL_NUMBER_HEXADECIMAL).underline = true;
|
||||
// scheme.getStyle(Token.LITERAL_NUMBER_HEXADECIMAL).background = Color.pink;
|
||||
|
||||
scheme.getStyle(Token.COMMENT_EOL).foreground = Color.lightGray;
|
||||
|
||||
// scheme.getStyle(Token.COMMENT_EOL).font = new Font("Georgia", Font.ITALIC, 10);
|
||||
|
||||
codeArea.revalidate();
|
||||
}
|
||||
|
||||
protected void compileCode() {
|
||||
|
||||
String code = codeArea.getText();
|
||||
String asmResult = "";
|
||||
|
||||
Pattern pattern = Pattern.compile("(.*?)init:(.*?)code:(.*?)", Pattern.DOTALL);
|
||||
Matcher matcher = pattern.matcher(code);
|
||||
|
||||
try {
|
||||
if (matcher.find()) {
|
||||
asmResult = SerpentCompiler.compileFullNotion(codeArea.getText());
|
||||
asmResult = GUIUtils.getStyledAsmCode(asmResult);
|
||||
} else {
|
||||
asmResult = SerpentCompiler.compile(codeArea.getText());
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
logger.error(th.getMessage(), th);
|
||||
|
||||
splitPanel.setDividerLocation(0.8);
|
||||
result.setVisible(true);
|
||||
result.setText(th.getMessage());
|
||||
result.setForeground(Color.RED);
|
||||
return;
|
||||
}
|
||||
result.setForeground(Color.BLACK.brighter());
|
||||
result.setVisible(true);
|
||||
result.setText(asmResult);
|
||||
|
||||
splitPanel.setDividerLocation(
|
||||
1 - result.getPreferredSize().getHeight() / codeArea.getPreferredSize().getHeight());
|
||||
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
protected byte[] prepareCodeForSend() {
|
||||
|
||||
String asmResult = "";
|
||||
byte[] machineCode = null;
|
||||
|
||||
try {
|
||||
String code = codeArea.getText();
|
||||
|
||||
Pattern pattern = Pattern.compile("(.*?)init:(.*?)code:(.*?)", Pattern.DOTALL);
|
||||
Matcher matcher = pattern.matcher(code);
|
||||
if (matcher.find()) {
|
||||
asmResult = SerpentCompiler.compileFullNotion(codeArea.getText());
|
||||
machineCode = SerpentCompiler.compileFullNotionAssemblyToMachine(asmResult);
|
||||
} else {
|
||||
asmResult = SerpentCompiler.compile(codeArea.getText());
|
||||
machineCode = SerpentCompiler.compileAssemblyToMachine(asmResult);
|
||||
machineCode = SerpentCompiler.encodeMachineCodeForVMRun(machineCode, null);
|
||||
}
|
||||
} catch (Throwable th) {
|
||||
logger.error(th.getMessage(), th);
|
||||
splitPanel.setDividerLocation(0.7);
|
||||
result.setVisible(true);
|
||||
result.setText(th.getMessage());
|
||||
result.setForeground(Color.RED);
|
||||
return null;
|
||||
}
|
||||
return machineCode;
|
||||
}
|
||||
|
||||
public void createToolBar() {
|
||||
|
||||
JToolBar toolbar = new JToolBar(SwingConstants.VERTICAL);
|
||||
toolbar.putClientProperty("JToolBar.isRollover", Boolean.TRUE);
|
||||
toolbar.setFloatable(false);
|
||||
final JPanel mainContentPane = SerpentEditor.this.contentPane;
|
||||
|
||||
{
|
||||
URL url = ClassLoader.getSystemResource("buttons/open-file.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
ImageIcon imageIcon = new ImageIcon(img);
|
||||
final JButton button = new JButton(imageIcon);
|
||||
button.setToolTipText("Open File < Ctrl + O >");
|
||||
|
||||
Action openFile = new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.doClick();
|
||||
}
|
||||
};
|
||||
|
||||
mainContentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).
|
||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK),
|
||||
"OpenFileButton");
|
||||
|
||||
mainContentPane.getActionMap().put("OpenFileButton", openFile);
|
||||
|
||||
button.addActionListener(e -> {
|
||||
File file = callFileChooser();
|
||||
try {
|
||||
if (file == null)
|
||||
return;
|
||||
String content = new Scanner(file).useDelimiter("\\Z").next();
|
||||
codeArea.setText(content);
|
||||
} catch (FileNotFoundException e1) {
|
||||
logger.error(e1.getMessage(), e1);
|
||||
} catch (java.util.NoSuchElementException e2) {
|
||||
// don't worry it's just the file is empty
|
||||
codeArea.setText("");
|
||||
}
|
||||
});
|
||||
toolbar.add(button);
|
||||
}
|
||||
|
||||
{
|
||||
URL url = ClassLoader.getSystemResource("buttons/save-file.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
ImageIcon imageIcon = new ImageIcon(img);
|
||||
final JButton button = new JButton(imageIcon);
|
||||
button.setToolTipText("Save File < Ctrl + S >");
|
||||
|
||||
Action saveNewFile = new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.doClick();
|
||||
}
|
||||
};
|
||||
|
||||
mainContentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).
|
||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK),
|
||||
"OpenSaveButtonAlways");
|
||||
|
||||
mainContentPane.getActionMap().put("OpenSaveButtonAlways", saveNewFile);
|
||||
|
||||
Action saveFile = new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.doClick();
|
||||
}
|
||||
};
|
||||
|
||||
mainContentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).
|
||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK),
|
||||
"OpenSaveButton");
|
||||
|
||||
mainContentPane.getActionMap().put("OpenSaveButton", saveFile);
|
||||
|
||||
button.addActionListener(e -> {
|
||||
|
||||
File file = null;
|
||||
|
||||
if (e.getModifiers() == (InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK)) {
|
||||
file = callFileChooser();
|
||||
if (file == null)
|
||||
return;
|
||||
} else if (fileChooser == null
|
||||
|| fileChooser.getSelectedFile() == null) {
|
||||
file = callFileChooser();
|
||||
if (file == null)
|
||||
return;
|
||||
} else {
|
||||
file = fileChooser.getSelectedFile();
|
||||
}
|
||||
|
||||
try {
|
||||
BufferedWriter out = new BufferedWriter(new FileWriter(file), 32768);
|
||||
out.write(codeArea.getText());
|
||||
out.close();
|
||||
} catch (IOException e1) {
|
||||
logger.error(e1.getMessage(), e1);
|
||||
}
|
||||
});
|
||||
toolbar.add(button);
|
||||
}
|
||||
toolbar.addSeparator();
|
||||
|
||||
{
|
||||
URL url = ClassLoader.getSystemResource("buttons/compile.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
ImageIcon imageIcon = new ImageIcon(img);
|
||||
final JButton button = new JButton(imageIcon);
|
||||
button.setToolTipText("Compile the contract < Ctrl + F9 >");
|
||||
|
||||
Action compile = new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.doClick();
|
||||
}
|
||||
};
|
||||
|
||||
mainContentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).
|
||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_F9, InputEvent.CTRL_DOWN_MASK),
|
||||
"CompileButton");
|
||||
|
||||
mainContentPane.getActionMap().put("CompileButton", compile);
|
||||
|
||||
button.addActionListener(e -> compileCode());
|
||||
toolbar.add(button);
|
||||
}
|
||||
|
||||
{
|
||||
URL url = ClassLoader.getSystemResource("buttons/deploy.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
ImageIcon imageIcon = new ImageIcon(img);
|
||||
final JButton button = new JButton(imageIcon);
|
||||
button.setToolTipText("Deploy contract to the chain < Ctrl + Shift + F9 >");
|
||||
|
||||
Action deploy = new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.doClick();
|
||||
}
|
||||
};
|
||||
|
||||
mainContentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).
|
||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_F9,
|
||||
InputEvent.SHIFT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK),
|
||||
"DeployButton");
|
||||
|
||||
mainContentPane.getActionMap().put("DeployButton", deploy);
|
||||
|
||||
button.addActionListener(e -> {
|
||||
byte[] machineCode = prepareCodeForSend();
|
||||
if (machineCode == null) return;
|
||||
ContractSubmitDialog payOutDialog =
|
||||
new ContractSubmitDialog((Frame) SwingUtilities.getAncestorOfClass(JFrame.class,
|
||||
contentPane), machineCode);
|
||||
});
|
||||
toolbar.add(button);
|
||||
}
|
||||
|
||||
{
|
||||
URL url = ClassLoader.getSystemResource("buttons/call.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
ImageIcon imageIcon = new ImageIcon(img);
|
||||
final JButton button = new JButton(imageIcon);
|
||||
button.setToolTipText("Call contract <Ctrl + F8>");
|
||||
|
||||
Action call = new AbstractAction() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
button.doClick();
|
||||
}
|
||||
};
|
||||
|
||||
mainContentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).
|
||||
put(KeyStroke.getKeyStroke(KeyEvent.VK_F8,
|
||||
InputEvent.CTRL_DOWN_MASK),
|
||||
"CallButton");
|
||||
|
||||
mainContentPane.getActionMap().put("CallButton", call);
|
||||
|
||||
button.addActionListener(e -> {
|
||||
ContractCallDialog payOutDialog = new ContractCallDialog(
|
||||
(Frame) SwingUtilities.getAncestorOfClass(
|
||||
JFrame.class, contentPane));
|
||||
});
|
||||
toolbar.add(button);
|
||||
}
|
||||
this.contentPane.add(toolbar, BorderLayout.EAST);
|
||||
}
|
||||
|
||||
|
||||
protected File callFileChooser() {
|
||||
|
||||
File file = null;
|
||||
|
||||
if (fileChooser == null) {
|
||||
fileChooser = new JFileChooser(CONFIG.samplesDir());
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
}
|
||||
|
||||
switch (fileChooser.showOpenDialog(SerpentEditor.this)) {
|
||||
case JFileChooser.APPROVE_OPTION:
|
||||
file = fileChooser.getSelectedFile();
|
||||
break;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
toolBar.editorToggle.setSelected(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Start all Swing applications on the EDT.
|
||||
SwingUtilities.invokeLater(() -> new SerpentEditor(null).setVisible(true));
|
||||
}
|
||||
}
|
|
@ -1,504 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.vm.OpCode;
|
||||
|
||||
import org.fife.ui.rsyntaxtextarea.AbstractTokenMaker;
|
||||
import org.fife.ui.rsyntaxtextarea.RSyntaxUtilities;
|
||||
import org.fife.ui.rsyntaxtextarea.Token;
|
||||
import org.fife.ui.rsyntaxtextarea.TokenMap;
|
||||
|
||||
import javax.swing.text.Segment;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 24.04.14
|
||||
*/
|
||||
public class SerpentTokenMaker extends AbstractTokenMaker {
|
||||
|
||||
// http://fifesoft.com/rsyntaxtextarea/doc/CustomSyntaxHighlighting.html
|
||||
|
||||
protected final String operators = ".@:*<>=?|!";
|
||||
|
||||
private int currentTokenStart;
|
||||
private int currentTokenType;
|
||||
|
||||
private boolean bracketVariable; // Whether a variable is of the format %{...}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public SerpentTokenMaker() {
|
||||
super(); // Initializes tokensToHighlight.
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the token to give it the exact ID it deserves before
|
||||
* being passed up to the super method.
|
||||
*
|
||||
* @param segment <code>Segment</code> to get text from.
|
||||
* @param start Start offset in <code>segment</code> of token.
|
||||
* @param end End offset in <code>segment</code> of token.
|
||||
* @param tokenType The token's type.
|
||||
* @param startOffset The offset in the document at which the token occurs.
|
||||
*/
|
||||
@Override
|
||||
public void addToken(Segment segment, int start, int end, int tokenType, int startOffset) {
|
||||
|
||||
switch (tokenType) {
|
||||
// Since reserved words, functions, and data types are all passed
|
||||
// into here as "identifiers," we have to see what the token
|
||||
// really is...
|
||||
case Token.IDENTIFIER:
|
||||
int value = wordsToHighlight.get(segment, start, end);
|
||||
if (value != -1)
|
||||
tokenType = value;
|
||||
break;
|
||||
|
||||
case Token.ANNOTATION:
|
||||
value = wordsToHighlight.get(segment, start, end);
|
||||
if (value != -1)
|
||||
tokenType = value;
|
||||
break;
|
||||
}
|
||||
super.addToken(segment, start, end, tokenType, startOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text to place at the beginning and end of a
|
||||
* line to "comment" it in a this programming language.
|
||||
*
|
||||
* @return The start and end strings to add to a line to "comment"
|
||||
* it out.
|
||||
*/
|
||||
@Override
|
||||
public String[] getLineCommentStartAndEnd() {
|
||||
return new String[]{"#", null};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether tokens of the specified type should have "mark
|
||||
* occurrences" enabled for the current programming language.
|
||||
*
|
||||
* @param type The token type.
|
||||
* @return Whether tokens of this type should have "mark occurrences"
|
||||
* enabled.
|
||||
*/
|
||||
@Override
|
||||
public boolean getMarkOccurrencesOfTokenType(int type) {
|
||||
return type == Token.IDENTIFIER || type == Token.VARIABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the words to highlight for Windows batch files.
|
||||
*
|
||||
* @return A <code>TokenMap</code> containing the words to highlight for
|
||||
* Windows batch files.
|
||||
* @see org.fife.ui.rsyntaxtextarea.AbstractTokenMaker#getWordsToHighlight
|
||||
*/
|
||||
@Override
|
||||
public TokenMap getWordsToHighlight() {
|
||||
|
||||
TokenMap tokenMap = new TokenMap(false); // Ignore case.
|
||||
|
||||
int reservedWord = Token.RESERVED_WORD;
|
||||
tokenMap.put("set", reservedWord);
|
||||
tokenMap.put("if", reservedWord);
|
||||
tokenMap.put("else", reservedWord);
|
||||
tokenMap.put("elif", reservedWord);
|
||||
tokenMap.put("seq", reservedWord);
|
||||
tokenMap.put("while", reservedWord);
|
||||
tokenMap.put("byte", reservedWord);
|
||||
tokenMap.put("access", reservedWord);
|
||||
tokenMap.put("arrset", reservedWord);
|
||||
tokenMap.put("set_and_inc", reservedWord);
|
||||
tokenMap.put("array", reservedWord);
|
||||
tokenMap.put("getch", reservedWord);
|
||||
tokenMap.put("setch", reservedWord);
|
||||
tokenMap.put("string", reservedWord);
|
||||
tokenMap.put("send", reservedWord);
|
||||
tokenMap.put("create", reservedWord);
|
||||
tokenMap.put("sha3", reservedWord);
|
||||
tokenMap.put("sha3bytes", reservedWord);
|
||||
tokenMap.put("sload", reservedWord);
|
||||
tokenMap.put("sstore", reservedWord);
|
||||
tokenMap.put("calldataload", reservedWord);
|
||||
tokenMap.put("id", reservedWord);
|
||||
tokenMap.put("return", reservedWord);
|
||||
tokenMap.put("suicide", reservedWord);
|
||||
|
||||
tokenMap.put("stop", reservedWord);
|
||||
|
||||
int function = Token.FUNCTION;
|
||||
tokenMap.put("msg", function);
|
||||
tokenMap.put("data", function);
|
||||
tokenMap.put("contract", function);
|
||||
tokenMap.put("storage", function);
|
||||
tokenMap.put("block", function);
|
||||
tokenMap.put("tx", function);
|
||||
|
||||
// ALL the assembly tokens
|
||||
int reservedWord2 = Token.RESERVED_WORD_2;
|
||||
for (OpCode value : OpCode.values()) {
|
||||
tokenMap.put(value.name(), reservedWord2);
|
||||
tokenMap.put("[asm", reservedWord2);
|
||||
tokenMap.put("asm]", reservedWord2);
|
||||
}
|
||||
|
||||
int dataType = Token.ANNOTATION;
|
||||
tokenMap.put("init", dataType);
|
||||
tokenMap.put("code", dataType);
|
||||
|
||||
return tokenMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a peerInfoList of tokens representing the given text.
|
||||
*
|
||||
* @param text The text to break into tokens.
|
||||
* @param startTokenType The token with which to start tokenizing.
|
||||
* @param startOffset The offset at which the line of tokens begins.
|
||||
* @return A linked peerInfoList of tokens representing <code>text</code>.
|
||||
*/
|
||||
public Token getTokenList(Segment text, int startTokenType, final int startOffset) {
|
||||
|
||||
resetTokenList();
|
||||
|
||||
char[] array = text.array;
|
||||
int offset = text.offset;
|
||||
int count = text.count;
|
||||
int end = offset + count;
|
||||
|
||||
// See, when we find a token, its starting position is always of the form:
|
||||
// 'startOffset + (currentTokenStart-offset)'; but since startOffset
|
||||
// offset are constant, tokens' starting positions become:
|
||||
// 'newStartOffset+currentTokenStart' for one less subtraction operation.
|
||||
int newStartOffset = startOffset - offset;
|
||||
|
||||
currentTokenStart = offset;
|
||||
currentTokenType = startTokenType;
|
||||
|
||||
//beginning:
|
||||
for (int i = offset; i < end; i++) {
|
||||
|
||||
char c = array[i];
|
||||
|
||||
switch (currentTokenType) {
|
||||
|
||||
case Token.NULL:
|
||||
|
||||
currentTokenStart = i; // Starting a new token here.
|
||||
|
||||
switch (c) {
|
||||
|
||||
case '#':
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
break;
|
||||
|
||||
|
||||
// The "separators".
|
||||
case '(':
|
||||
case ')':
|
||||
addToken(text, currentTokenStart, i, Token.SEPARATOR, newStartOffset + currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
// The "separators2".
|
||||
case ',':
|
||||
case ';':
|
||||
addToken(text, currentTokenStart, i, Token.IDENTIFIER, newStartOffset + currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
// Newer version of EOL comments, or a label
|
||||
case ':':
|
||||
// If this will be the first token added, it is
|
||||
// a new-style comment or a label
|
||||
if (firstToken == null) {
|
||||
if (i < end - 1 && array[i + 1] == ':') { // new-style comment
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
} else { // Label
|
||||
currentTokenType = Token.PREPROCESSOR;
|
||||
}
|
||||
} else { // Just a colon
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
}
|
||||
break;
|
||||
// Newer version of EOL comments, or a label
|
||||
|
||||
default:
|
||||
// Just to speed things up a tad, as this will usually be the case (if spaces above failed).
|
||||
if (RSyntaxUtilities.isLetterOrDigit(c) || c == '\\') {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
|
||||
int indexOf = operators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i, Token.OPERATOR, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
} else {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
} // End of switch (c).
|
||||
break;
|
||||
|
||||
case Token.WHITESPACE:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case '/':
|
||||
addToken(text, currentTokenStart, i - 1,
|
||||
Token.COMMENT_EOL, newStartOffset + currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
break; // Still whitespace.
|
||||
|
||||
case '"':
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
break;
|
||||
|
||||
|
||||
// The "separators".
|
||||
case '(':
|
||||
case ')':
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
// The "separators2".
|
||||
case ',':
|
||||
case ';':
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
// Newer version of EOL comments, or a label
|
||||
case ':':
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
// If the previous (whitespace) token was the first token
|
||||
// added, this is a new-style comment or a label
|
||||
if (firstToken.getNextToken() == null) {
|
||||
if (i < end - 1 && array[i + 1] == ':') { // new-style comment
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
} else { // Label
|
||||
currentTokenType = Token.PREPROCESSOR;
|
||||
}
|
||||
} else { // Just a colon
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
}
|
||||
break;
|
||||
|
||||
default: // Add the whitespace token and start anew.
|
||||
addToken(text, currentTokenStart, i - 1, Token.WHITESPACE, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
|
||||
// Just to speed things up a tad, as this will usually be the case (if spaces above failed).
|
||||
if (RSyntaxUtilities.isLetterOrDigit(c) || c == '\\') {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
break;
|
||||
}
|
||||
|
||||
int indexOf = operators.indexOf(c, 0);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i, Token.OPERATOR, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
} else {
|
||||
currentTokenType = Token.IDENTIFIER;
|
||||
}
|
||||
} // End of switch (c).
|
||||
break;
|
||||
|
||||
default: // Should never happen
|
||||
case Token.IDENTIFIER:
|
||||
|
||||
switch (c) {
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
// Check for REM comments.
|
||||
if (i - currentTokenStart == 3 &&
|
||||
(array[i - 3] == 'r' || array[i - 3] == 'R') &&
|
||||
(array[i - 2] == 'e' || array[i - 2] == 'E') &&
|
||||
(array[i - 1] == 'm' || array[i - 1] == 'M')) {
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
break;
|
||||
}
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.WHITESPACE;
|
||||
break;
|
||||
|
||||
case '"':
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
currentTokenStart = i;
|
||||
currentTokenType = Token.ERROR_STRING_DOUBLE;
|
||||
break;
|
||||
|
||||
|
||||
// Should be part of identifiers, but not at end of "REM".
|
||||
case '\\':
|
||||
// Check for REM comments.
|
||||
if (i - currentTokenStart == 3 &&
|
||||
(array[i - 3] == 'r' || array[i - 3] == 'R') &&
|
||||
(array[i - 2] == 'e' || array[i - 2] == 'E') &&
|
||||
(array[i - 1] == 'm' || array[i - 1] == 'M')) {
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
}
|
||||
break;
|
||||
|
||||
// case '.':
|
||||
case '_':
|
||||
break; // Characters good for identifiers.
|
||||
|
||||
// The "separators".
|
||||
case '(':
|
||||
case ')':
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.SEPARATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
// The "separators2".
|
||||
case ',':
|
||||
case ';':
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.IDENTIFIER, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
// Just to speed things up a tad, as this will usually be the case.
|
||||
if (RSyntaxUtilities.isLetterOrDigit(c) || c == '\\') {
|
||||
break;
|
||||
}
|
||||
|
||||
int indexOf = operators.indexOf(c);
|
||||
if (indexOf > -1) {
|
||||
addToken(text, currentTokenStart, i - 1, Token.IDENTIFIER, newStartOffset +
|
||||
currentTokenStart);
|
||||
addToken(text, i, i, Token.OPERATOR, newStartOffset + i);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
// Otherwise, fall through and assume we're still okay as an IDENTIFIER...
|
||||
} // End of switch (c).
|
||||
break;
|
||||
|
||||
case Token.COMMENT_EOL:
|
||||
|
||||
if (i + 1 >= array.length)
|
||||
break;
|
||||
|
||||
char nextC = array[i + 1];
|
||||
if (nextC == '/') {
|
||||
|
||||
i = end - 1;
|
||||
addToken(text, currentTokenStart, i, Token.COMMENT_EOL, newStartOffset + currentTokenStart);
|
||||
// We need to set token type to null so at the bottom we don't add one more token.
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case Token.PREPROCESSOR: // Used for labels
|
||||
i = end - 1;
|
||||
addToken(text, currentTokenStart, i, Token.PREPROCESSOR, newStartOffset + currentTokenStart);
|
||||
// We need to set token type to null so at the bottom we don't add one more token.
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
|
||||
case Token.ERROR_STRING_DOUBLE:
|
||||
|
||||
if (c == '"') {
|
||||
addToken(text, currentTokenStart, i, Token.LITERAL_STRING_DOUBLE_QUOTE, newStartOffset + currentTokenStart);
|
||||
currentTokenStart = i + 1;
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
// Otherwise, we're still an unclosed string...
|
||||
break;
|
||||
|
||||
case Token.VARIABLE:
|
||||
|
||||
if (i == currentTokenStart + 1) { // first character after '%'.
|
||||
bracketVariable = false;
|
||||
switch (c) {
|
||||
case '{':
|
||||
bracketVariable = true;
|
||||
break;
|
||||
default:
|
||||
if (RSyntaxUtilities.isLetter(c) || c == ' ') { // No tab, just space; spaces are okay in variable names.
|
||||
break;
|
||||
} else if (RSyntaxUtilities.isDigit(c)) { // Single-digit command-line argument ("%1").
|
||||
addToken(text, currentTokenStart, i, Token.VARIABLE, newStartOffset + currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
} else { // Anything else, ???.
|
||||
addToken(text, currentTokenStart, i - 1, Token.VARIABLE, newStartOffset + currentTokenStart); // ???
|
||||
i--;
|
||||
currentTokenType = Token.NULL;
|
||||
break;
|
||||
}
|
||||
} // End of switch (c).
|
||||
} else { // Character other than first after the '%'.
|
||||
if (bracketVariable == true) {
|
||||
if (c == '}') {
|
||||
addToken(text, currentTokenStart, i, Token.VARIABLE, newStartOffset + currentTokenStart);
|
||||
currentTokenType = Token.NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
} // End of switch (currentTokenType).
|
||||
|
||||
} // End of for (int i=offset; i<end; i++).
|
||||
|
||||
// Deal with the (possibly there) last token.
|
||||
if (currentTokenType != Token.NULL) {
|
||||
// Check for REM comments.
|
||||
if (end - currentTokenStart == 3 &&
|
||||
(array[end - 3] == 'r' || array[end - 3] == 'R') &&
|
||||
(array[end - 2] == 'e' || array[end - 2] == 'E') &&
|
||||
(array[end - 1] == 'm' || array[end - 1] == 'M')) {
|
||||
currentTokenType = Token.COMMENT_EOL;
|
||||
}
|
||||
addToken(text, currentTokenStart, end - 1, currentTokenType, newStartOffset + currentTokenStart);
|
||||
}
|
||||
addNullToken();
|
||||
// Return the first token in our linked peerInfoList.
|
||||
return firstToken;
|
||||
}
|
||||
}
|
|
@ -1,310 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.ethereum.vm.Program;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class StateExplorerWindow extends JFrame {
|
||||
|
||||
private ToolBar toolBar = null;
|
||||
private JTextField txfAccountAddress;
|
||||
private WindowTextArea txaPrinter;
|
||||
private JButton btnPlayCode;
|
||||
private AccountsListWindow accountsListWindow;
|
||||
ProgramPlayDialog codePanel;
|
||||
|
||||
private JTable tblStateDataTable;
|
||||
private StateDataTableModel dataModel;
|
||||
String[] dataTypes = {"String", "Hex", "Number"};
|
||||
|
||||
public StateExplorerWindow(ToolBar toolBar) {
|
||||
this.toolBar = toolBar;
|
||||
|
||||
URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
setTitle("State Explorer");
|
||||
setSize(700, 530);
|
||||
setLocation(50, 180);
|
||||
setResizable(false);
|
||||
|
||||
/*
|
||||
* top search panel
|
||||
*/
|
||||
JPanel panel = new JPanel();
|
||||
getContentPane().add(panel);
|
||||
|
||||
Box horizontalBox = Box.createHorizontalBox();
|
||||
panel.add(horizontalBox);
|
||||
|
||||
java.net.URL imageURL = ClassLoader.getSystemResource("buttons/list.png");
|
||||
ImageIcon image = new ImageIcon(imageURL);
|
||||
JToggleButton btnListAccounts = new JToggleButton("");
|
||||
btnListAccounts.setIcon(image);
|
||||
btnListAccounts.setContentAreaFilled(true);
|
||||
btnListAccounts.setToolTipText("Serpent Editor");
|
||||
btnListAccounts.setBackground(Color.WHITE);
|
||||
btnListAccounts.setBorderPainted(false);
|
||||
btnListAccounts.setFocusPainted(false);
|
||||
btnListAccounts.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
btnListAccounts.addItemListener(e -> SwingUtilities.invokeLater(() -> {
|
||||
if (accountsListWindow == null)
|
||||
accountsListWindow = new AccountsListWindow();
|
||||
accountsListWindow.setVisible(true);
|
||||
}));
|
||||
horizontalBox.add(btnListAccounts);
|
||||
|
||||
|
||||
txfAccountAddress = new JTextField();
|
||||
horizontalBox.add(txfAccountAddress);
|
||||
txfAccountAddress.setColumns(30);
|
||||
|
||||
JButton btnSearch = new JButton("Search");
|
||||
horizontalBox.add(btnSearch);
|
||||
btnSearch.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
byte[] addr = Utils.addressStringToBytes(txfAccountAddress.getText());
|
||||
if (addr != null)
|
||||
searchAccount(addr);
|
||||
}
|
||||
});
|
||||
|
||||
btnPlayCode = new JButton("Play Code");
|
||||
horizontalBox.add(btnPlayCode);
|
||||
btnPlayCode.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
byte[] addr = Utils.addressStringToBytes(txfAccountAddress.getText());
|
||||
if (addr != null) {
|
||||
Repository repository = UIEthereumManager.ethereum.getRepository();
|
||||
byte[] code = repository.getCode(addr);
|
||||
if (code != null)
|
||||
ProgramPlayDialog.createAndShowGUI(code, null, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* center text panel
|
||||
*/
|
||||
JPanel centerPanel = new JPanel();
|
||||
panel.add(centerPanel);
|
||||
|
||||
txaPrinter = new WindowTextArea();
|
||||
centerPanel.add(txaPrinter);
|
||||
|
||||
/*
|
||||
* bottom data panel
|
||||
*/
|
||||
// data type choice boxes
|
||||
Box Hbox = Box.createHorizontalBox();
|
||||
panel.add(Hbox);
|
||||
|
||||
Box VBox1 = Box.createVerticalBox();
|
||||
JLabel l1 = new JLabel("Key Encoding");
|
||||
l1.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
JComboBox cmbKey = new JComboBox(dataTypes);
|
||||
cmbKey.setSelectedIndex(1);
|
||||
cmbKey.addActionListener(e -> {
|
||||
JComboBox cmb = (JComboBox) e.getSource();
|
||||
DataEncodingType t = DataEncodingType.getTypeFromString((String) cmb.getSelectedItem());
|
||||
dataModel.setKeyEncoding(t);
|
||||
});
|
||||
VBox1.add(l1);
|
||||
VBox1.add(cmbKey);
|
||||
|
||||
Box VBox2 = Box.createVerticalBox();
|
||||
VBox2.setAlignmentX(LEFT_ALIGNMENT);
|
||||
JLabel l2 = new JLabel("Value Encoding");
|
||||
l2.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
JComboBox cmbValue = new JComboBox(dataTypes);
|
||||
cmbValue.setSelectedIndex(1);
|
||||
cmbValue.addActionListener(e -> {
|
||||
JComboBox cmb = (JComboBox) e.getSource();
|
||||
DataEncodingType t = DataEncodingType.getTypeFromString((String) cmb.getSelectedItem());
|
||||
dataModel.setValueEncoding(t);
|
||||
});
|
||||
VBox2.add(l2);
|
||||
VBox2.add(cmbValue);
|
||||
|
||||
Hbox.add(VBox1);
|
||||
|
||||
JPanel spacer = new JPanel();
|
||||
FlowLayout flowLayout = (FlowLayout) spacer.getLayout();
|
||||
flowLayout.setHgap(100);
|
||||
Hbox.add(spacer);
|
||||
Hbox.add(VBox2);
|
||||
|
||||
// table
|
||||
tblStateDataTable = new JTable();
|
||||
dataModel = new StateDataTableModel();
|
||||
tblStateDataTable.setModel(dataModel);
|
||||
|
||||
|
||||
JScrollPane scrollPane = new JScrollPane(tblStateDataTable);
|
||||
scrollPane.setPreferredSize(new Dimension(600, 200));
|
||||
panel.add(scrollPane);
|
||||
}
|
||||
|
||||
private void searchAccount(byte[] add) {
|
||||
txaPrinter.clean();
|
||||
txaPrinter.println(accountDetailsString(add, dataModel));
|
||||
}
|
||||
|
||||
private String accountDetailsString(byte[] account, StateDataTableModel dataModel) {
|
||||
String ret = "";
|
||||
// 1) print account address
|
||||
ret = "Account: " + Hex.toHexString(account) + "\n";
|
||||
|
||||
//2) print state
|
||||
Repository repository = UIEthereumManager.ethereum.getRepository();
|
||||
AccountState state = repository.getAccountState(account);
|
||||
if (state != null)
|
||||
ret += state.toString() + "\n";
|
||||
|
||||
//3) print storage
|
||||
ContractDetails contractDetails = repository.getContractDetails(account);
|
||||
if (contractDetails != null) {
|
||||
Map<DataWord, DataWord> accountStorage = contractDetails.getStorage();
|
||||
dataModel.setData(accountStorage);
|
||||
}
|
||||
|
||||
//4) code print
|
||||
byte[] code = repository.getCode(account);
|
||||
if (code != null) {
|
||||
ret += "\n\nCode:\n";
|
||||
ret += Program.stringify(code, 0, "");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private class StateDataTableModel extends AbstractTableModel {
|
||||
|
||||
Map<DataWord, DataWord> data;
|
||||
DataEncodingType keyEncodingType = DataEncodingType.HEX;
|
||||
DataEncodingType valueEncodingType = DataEncodingType.HEX;
|
||||
String[] columns = new String[]{"Key", "Value"};
|
||||
|
||||
public StateDataTableModel() {
|
||||
}
|
||||
|
||||
public StateDataTableModel(Map<DataWord, DataWord> initData) {
|
||||
setData(initData);
|
||||
}
|
||||
|
||||
public void setData(Map<DataWord, DataWord> initData) {
|
||||
data = initData;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void setKeyEncoding(DataEncodingType type) {
|
||||
keyEncodingType = type;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void setValueEncoding(DataEncodingType type) {
|
||||
valueEncodingType = type;
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getColumnName(int column) {
|
||||
return columns[column];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return data == null ? 0 : data.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return columns.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueAt(int rowIndex, int columnIndex) {
|
||||
DataWord key = (DataWord) this.data.keySet().toArray()[rowIndex];
|
||||
|
||||
if (columnIndex == 0) {
|
||||
return getDataWithEncoding(key.getData(), keyEncodingType);
|
||||
} else {
|
||||
DataWord value = this.data.get(key);
|
||||
return getDataWithEncoding(value.getData(), valueEncodingType);
|
||||
}
|
||||
}
|
||||
|
||||
private String getDataWithEncoding(byte[] data, DataEncodingType enc) {
|
||||
switch (enc) {
|
||||
case STRING:
|
||||
return new String(data);
|
||||
case HEX:
|
||||
return Hex.toHexString(data);
|
||||
case NUMBER:
|
||||
return new BigInteger(data).toString();
|
||||
}
|
||||
|
||||
return data.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private enum DataEncodingType {
|
||||
STRING,
|
||||
HEX,
|
||||
NUMBER;
|
||||
|
||||
static public DataEncodingType getTypeFromString(String value) {
|
||||
switch (value) {
|
||||
case "String":
|
||||
return STRING;
|
||||
case "Hex":
|
||||
return HEX;
|
||||
case "Number":
|
||||
return NUMBER;
|
||||
}
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
|
||||
private class WindowTextArea extends TextArea {
|
||||
|
||||
public WindowTextArea() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void println(String txt) {
|
||||
setText(getText() + txt + "\n");
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
setText("");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Start all Swing applications on the EDT.
|
||||
SwingUtilities.invokeLater(() -> new StateExplorerWindow(null).setVisible(true));
|
||||
}
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.facade.Ethereum;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 30.04.14
|
||||
*/
|
||||
public class ToolBar extends JFrame {
|
||||
|
||||
private Logger introLogger = LoggerFactory.getLogger("Intro");
|
||||
|
||||
private ConnectionConsoleWindow connectionConsoleWindow = null;
|
||||
private PeersTableWindow mainFrame = null;
|
||||
private BlockChainTable blockchainWindow = null;
|
||||
private WalletWindow walletWindow = null;
|
||||
private SerpentEditor serpentEditor = null;
|
||||
private StateExplorerWindow stateExplorerWindow = null;
|
||||
|
||||
JToggleButton editorToggle;
|
||||
JToggleButton logToggle;
|
||||
JToggleButton peersToggle;
|
||||
JToggleButton chainToggle;
|
||||
JToggleButton walletToggle;
|
||||
JToggleButton stateExplorer;
|
||||
|
||||
public ToolBar() throws HeadlessException {
|
||||
|
||||
String version = SystemProperties.CONFIG.projectVersion();
|
||||
|
||||
introLogger.info("");
|
||||
introLogger.info("|Ξ| EthereumJ [v" + version + "]");
|
||||
introLogger.info("|Ξ| Code by Roman Mandeleil, (c) 2014.");
|
||||
introLogger.info("|Ξ| Contribution: Nick Savers ");
|
||||
introLogger.info("|Ξ| Based on a design by Vitalik Buterin.");
|
||||
introLogger.info("");
|
||||
introLogger.info("java.version: " + System.getProperty("java.version"));
|
||||
introLogger.info("java.home: " + System.getProperty("java.home"));
|
||||
introLogger.info("java.vendor: " + System.getProperty("java.vendor"));
|
||||
introLogger.info("");
|
||||
|
||||
if (Utils.JAVA_VERSION < 1.7 && Utils.JAVA_VERSION != 0) {
|
||||
introLogger.info("EthereumJ support version 1.7 and higher of Java Runtime please update");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
final JPanel cp = new JPanel(new FlowLayout());
|
||||
cp.setBackground(Color.WHITE);
|
||||
|
||||
java.net.URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
this.setSize(350, 200);
|
||||
this.setLocation(460, 25);
|
||||
this.setAlwaysOnTop(true);
|
||||
this.setResizable(false);
|
||||
this.setBackground(Color.WHITE);
|
||||
|
||||
setTitle("EthereumJ Studio");
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
UIEthereumManager.ethereum.close();
|
||||
}
|
||||
});
|
||||
|
||||
this.setContentPane(cp);
|
||||
|
||||
java.net.URL imageURL_1 = ClassLoader.getSystemResource("buttons/feedly.png");
|
||||
ImageIcon image_1 = new ImageIcon(imageURL_1);
|
||||
|
||||
java.net.URL imageURL_2 = ClassLoader.getSystemResource("buttons/winamp.png");
|
||||
ImageIcon image_2 = new ImageIcon(imageURL_2);
|
||||
|
||||
java.net.URL imageURL_3 = ClassLoader.getSystemResource("buttons/browser.png");
|
||||
ImageIcon image_3 = new ImageIcon(imageURL_3);
|
||||
|
||||
java.net.URL imageURL_4 = ClassLoader.getSystemResource("buttons/shazam.png");
|
||||
ImageIcon image_4 = new ImageIcon(imageURL_4);
|
||||
|
||||
java.net.URL imageURL_5 = ClassLoader.getSystemResource("buttons/wallet.png");
|
||||
ImageIcon image_5 = new ImageIcon(imageURL_5);
|
||||
|
||||
java.net.URL imageURL_6 = ClassLoader.getSystemResource("buttons/stateExplorer.png");
|
||||
ImageIcon image_6 = new ImageIcon(imageURL_6);
|
||||
|
||||
editorToggle = new JToggleButton("");
|
||||
editorToggle.setIcon(image_1);
|
||||
editorToggle.setContentAreaFilled(true);
|
||||
editorToggle.setToolTipText("Serpent Editor");
|
||||
editorToggle.setBackground(Color.WHITE);
|
||||
editorToggle.setBorderPainted(false);
|
||||
editorToggle.setFocusPainted(false);
|
||||
editorToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
editorToggle.addItemListener(e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (serpentEditor == null)
|
||||
serpentEditor = new SerpentEditor(ToolBar.this);
|
||||
serpentEditor.setVisible(true);
|
||||
});
|
||||
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||
serpentEditor.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
logToggle = new JToggleButton();
|
||||
logToggle.setIcon(image_2);
|
||||
logToggle.setToolTipText("Connect");
|
||||
logToggle.setContentAreaFilled(true);
|
||||
logToggle.setBackground(Color.WHITE);
|
||||
logToggle.setBorderPainted(false);
|
||||
logToggle.setFocusPainted(false);
|
||||
logToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
logToggle.addItemListener(e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (connectionConsoleWindow == null)
|
||||
connectionConsoleWindow = new ConnectionConsoleWindow(ToolBar.this);
|
||||
connectionConsoleWindow.setVisible(true);
|
||||
});
|
||||
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||
connectionConsoleWindow.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
peersToggle = new JToggleButton();
|
||||
peersToggle.setIcon(image_3);
|
||||
peersToggle.setToolTipText("Peers");
|
||||
peersToggle.setContentAreaFilled(true);
|
||||
peersToggle.setBackground(Color.WHITE);
|
||||
peersToggle.setBorderPainted(false);
|
||||
peersToggle.setFocusPainted(false);
|
||||
peersToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
peersToggle.addItemListener(e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (mainFrame == null)
|
||||
mainFrame = new PeersTableWindow(ToolBar.this);
|
||||
mainFrame.setVisible(true);
|
||||
});
|
||||
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||
mainFrame.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
chainToggle = new JToggleButton();
|
||||
chainToggle.setIcon(image_4);
|
||||
chainToggle.setToolTipText("Block Chain");
|
||||
chainToggle.setContentAreaFilled(true);
|
||||
chainToggle.setBackground(Color.WHITE);
|
||||
chainToggle.setBorderPainted(false);
|
||||
chainToggle.setFocusPainted(false);
|
||||
chainToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
chainToggle.addItemListener(e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
|
||||
if (blockchainWindow == null)
|
||||
blockchainWindow = new BlockChainTable(ToolBar.this);
|
||||
blockchainWindow.setVisible(true);
|
||||
});
|
||||
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||
blockchainWindow.setVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
walletToggle = new JToggleButton();
|
||||
walletToggle.setIcon(image_5);
|
||||
walletToggle.setToolTipText("Wallet");
|
||||
walletToggle.setContentAreaFilled(true);
|
||||
walletToggle.setBackground(Color.WHITE);
|
||||
walletToggle.setBorderPainted(false);
|
||||
walletToggle.setFocusPainted(false);
|
||||
walletToggle.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
walletToggle.addItemListener(
|
||||
e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (walletWindow == null)
|
||||
walletWindow = new WalletWindow(ToolBar.this);
|
||||
walletWindow.setVisible(true);
|
||||
});
|
||||
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||
walletWindow.setVisible(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
stateExplorer = new JToggleButton();
|
||||
stateExplorer.setIcon(image_6);
|
||||
stateExplorer.setToolTipText("State Explorer");
|
||||
stateExplorer.setContentAreaFilled(true);
|
||||
stateExplorer.setBackground(Color.WHITE);
|
||||
stateExplorer.setBorderPainted(false);
|
||||
stateExplorer.setFocusPainted(false);
|
||||
stateExplorer.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
stateExplorer.addItemListener(
|
||||
e -> {
|
||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (stateExplorerWindow == null)
|
||||
stateExplorerWindow = new StateExplorerWindow(ToolBar.this);
|
||||
stateExplorerWindow.setVisible(true);
|
||||
});
|
||||
} else if (e.getStateChange() == ItemEvent.DESELECTED) {
|
||||
stateExplorerWindow.setVisible(false);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
cp.add(editorToggle);
|
||||
cp.add(logToggle);
|
||||
cp.add(peersToggle);
|
||||
cp.add(chainToggle);
|
||||
cp.add(walletToggle);
|
||||
cp.add(stateExplorer);
|
||||
|
||||
Ethereum ethereum = UIEthereumManager.ethereum;
|
||||
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
SwingUtilities.invokeLater(() -> new ToolBar().setVisible(true));
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.util.ByteUtil;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.text.BadLocationException;
|
||||
import javax.swing.text.Highlighter;
|
||||
|
||||
/**
|
||||
* @author Adrian Benko
|
||||
* @since 27.08.14
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.facade.Ethereum;
|
||||
import org.ethereum.facade.EthereumFactory;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 01.09.2014
|
||||
*/
|
||||
public class UIEthereumManager {
|
||||
public static Ethereum ethereum = EthereumFactory.createEthereum();
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Account;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 17.05.14
|
||||
*/
|
||||
public class WalletAddressPanel extends JPanel {
|
||||
|
||||
public WalletAddressPanel(final Account account) {
|
||||
|
||||
final WalletAddressPanel walletAddressPanel = this;
|
||||
|
||||
this.setBackground(Color.WHITE);
|
||||
this.setPreferredSize(new Dimension(500, 45));
|
||||
|
||||
JTextField addressField = new JTextField();
|
||||
Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
Border empty = new EmptyBorder(5, 8, 5, 8);
|
||||
CompoundBorder border = new CompoundBorder(line, empty);
|
||||
addressField.setBorder(border);
|
||||
addressField.setEnabled(true);
|
||||
addressField.setEditable(false);
|
||||
addressField.setText(Hex.toHexString(account.getEcKey().getAddress()).toUpperCase());
|
||||
addressField.setForeground(new Color(143, 170, 220));
|
||||
addressField.setFont(new Font("Monospaced", 0, 12));
|
||||
addressField.setPreferredSize(new Dimension(300, 35));
|
||||
addressField.setBackground(Color.WHITE);
|
||||
this.add(addressField);
|
||||
|
||||
JTextField amount = new JTextField();
|
||||
amount.setBorder(border);
|
||||
amount.setEnabled(true);
|
||||
amount.setEditable(false);
|
||||
BigInteger balance = account.getBalance();
|
||||
|
||||
amount.setText(Utils.getValueShortString(balance));
|
||||
amount.setForeground(new Color(143, 170, 220));
|
||||
amount.setBackground(Color.WHITE);
|
||||
amount.setPreferredSize(new Dimension(100, 35));
|
||||
amount.setFont(new Font("Monospaced", 0, 13));
|
||||
amount.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
this.add(amount);
|
||||
|
||||
URL payoutIconURL = ClassLoader.getSystemResource("buttons/wallet-pay.png");
|
||||
ImageIcon payOutIcon = new ImageIcon(payoutIconURL);
|
||||
JLabel payOutLabel = new JLabel(payOutIcon);
|
||||
payOutLabel.setToolTipText("Payout for address");
|
||||
payOutLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
payOutLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
|
||||
PayOutDialog payOutDialog =
|
||||
new PayOutDialog((Frame) SwingUtilities.getAncestorOfClass(JFrame.class,
|
||||
walletAddressPanel), account);
|
||||
}
|
||||
});
|
||||
|
||||
this.add(payOutLabel);
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 17.05.14
|
||||
*/
|
||||
public class WalletSumPanel extends JPanel {
|
||||
|
||||
public WalletSumPanel(BigInteger balance) {
|
||||
|
||||
this.setBackground(Color.WHITE);
|
||||
double width = this.getSize().getWidth();
|
||||
this.setPreferredSize(new Dimension(500, 50));
|
||||
Border line = BorderFactory.createLineBorder(Color.LIGHT_GRAY);
|
||||
Border empty = new EmptyBorder(5, 8, 5, 8);
|
||||
CompoundBorder border = new CompoundBorder(line, empty);
|
||||
|
||||
JLabel addressField = new JLabel();
|
||||
addressField.setPreferredSize(new Dimension(300, 35));
|
||||
this.add(addressField);
|
||||
|
||||
JTextField amount = new JTextField();
|
||||
amount.setBorder(border);
|
||||
amount.setEnabled(true);
|
||||
amount.setEditable(false);
|
||||
amount.setText(Utils.getValueShortString(balance));
|
||||
|
||||
amount.setPreferredSize(new Dimension(100, 35));
|
||||
amount.setForeground(new Color(143, 170, 220));
|
||||
amount.setHorizontalAlignment(SwingConstants.RIGHT);
|
||||
amount.setFont(new Font("Monospaced", 0, 13));
|
||||
amount.setBackground(Color.WHITE);
|
||||
this.add(amount);
|
||||
|
||||
URL payoutIconURL = ClassLoader.getSystemResource("buttons/wallet-pay.png");
|
||||
ImageIcon payOutIcon = new ImageIcon(payoutIconURL);
|
||||
JLabel payOutLabel = new JLabel(payOutIcon);
|
||||
payOutLabel.setToolTipText("Payout for all address list");
|
||||
payOutLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
payOutLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
JOptionPane.showMessageDialog(null, "Under construction");
|
||||
}
|
||||
});
|
||||
|
||||
this.add(payOutLabel);
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
package org.ethereum.gui;
|
||||
|
||||
import org.ethereum.core.Account;
|
||||
import org.ethereum.core.Wallet;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @since 17.05.14
|
||||
*/
|
||||
public class WalletWindow extends JFrame implements Wallet.WalletListener {
|
||||
|
||||
WalletWindow walletWindow;
|
||||
ToolBar toolBar;
|
||||
|
||||
public WalletWindow(ToolBar toolBar) {
|
||||
|
||||
addCloseAction();
|
||||
this.toolBar = toolBar;
|
||||
|
||||
walletWindow = this;
|
||||
URL url = ClassLoader.getSystemResource("ethereum-icon.png");
|
||||
Toolkit kit = Toolkit.getDefaultToolkit();
|
||||
Image img = kit.createImage(url);
|
||||
this.setIconImage(img);
|
||||
setTitle("Ethereum Wallet");
|
||||
setSize(550, 280);
|
||||
setLocation(215, 280);
|
||||
setResizable(false);
|
||||
|
||||
Container contentPane = this.getContentPane();
|
||||
contentPane.setBackground(new Color(255, 255, 255));
|
||||
|
||||
Wallet wallet = UIEthereumManager.ethereum.getWallet();
|
||||
wallet.addListener(this);
|
||||
loadWallet();
|
||||
|
||||
}
|
||||
|
||||
private void loadWallet() {
|
||||
|
||||
Container contentPane = this.getContentPane();
|
||||
contentPane.removeAll();
|
||||
contentPane.setLayout(new FlowLayout());
|
||||
|
||||
Wallet wallet = UIEthereumManager.ethereum.getWallet();
|
||||
|
||||
for (Account account : wallet.getAccountCollection()) {
|
||||
WalletAddressPanel rowPanel = new WalletAddressPanel(account);
|
||||
contentPane.add(rowPanel);
|
||||
}
|
||||
|
||||
WalletSumPanel sumPanel = new WalletSumPanel(wallet.totalBalance());
|
||||
contentPane.add(sumPanel);
|
||||
|
||||
// TODO: move this to some add button method
|
||||
URL addAddressIconURL = ClassLoader.getSystemResource("buttons/add-address.png");
|
||||
ImageIcon addAddressIcon = new ImageIcon(addAddressIconURL);
|
||||
JLabel addAddressLabel = new JLabel(addAddressIcon);
|
||||
addAddressLabel.setToolTipText("Add new address");
|
||||
addAddressLabel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
||||
addAddressLabel.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
|
||||
Wallet wallet = UIEthereumManager.ethereum.getWallet();
|
||||
if (wallet.getAccountCollection().size() >= 5) {
|
||||
JOptionPane.showMessageDialog(walletWindow,
|
||||
"Hey do you really need more than 5 address for a demo wallet");
|
||||
return;
|
||||
}
|
||||
|
||||
wallet.addNewAccount();
|
||||
Dimension dimension = walletWindow.getSize();
|
||||
int height = dimension.height;
|
||||
int width = dimension.width;
|
||||
|
||||
Dimension newDimension = new Dimension(width, (height + 45));
|
||||
walletWindow.setSize(newDimension);
|
||||
}
|
||||
});
|
||||
contentPane.add(addAddressLabel);
|
||||
contentPane.revalidate();
|
||||
contentPane.repaint();
|
||||
}
|
||||
|
||||
public void addCloseAction() {
|
||||
this.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosing(WindowEvent e) {
|
||||
toolBar.walletToggle.setSelected(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged() {
|
||||
loadWallet();
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
java -Xmx6144M -Dlog4j.configuration=file:./config/log4j.properties -jar ./lib/ethereumj-0.7.9.jar org.ethereum.Start %*
|
|
@ -1 +0,0 @@
|
|||
java -Xmx6144M -Dlog4j.configuration=file:./config/log4j.properties -jar ./lib/ethereumj-0.7.9*.jar org.ethereum.Start -o true $@
|
|
@ -1,2 +0,0 @@
|
|||
call javaw -Xmx6144M -Dlog4j.configuration=file:./config/log4j.properties -jar ethereumj-studio.jar
|
||||
pause
|
|
@ -1 +0,0 @@
|
|||
java -Xmx6144M -Dlog4j.configuration=file:./config/log4j.properties -jar ethereumj-studio.jar -o true
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue