blob: 78199c2e4867413053e76990303b210e52e83c1e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020 RBEI and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v. 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Abirami Bhologa Indiran - Initial contribution and API
* Adhith Gopal
*******************************************************************************/
package org.eclipse.blockchain.ui.views;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.blockchain.core.BlockchainCore;
import org.eclipse.blockchain.core.BlockchainViewsRegistry;
import org.eclipse.blockchain.core.Web3jHandler;
import org.eclipse.blockchain.core.interfaces.IBlockchainView;
import org.eclipse.blockchain.core.model.TransactionModel;
import org.eclipse.blockchain.ui.Activator;
import org.eclipse.fx.ui.workbench3.FXViewPart;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.OverrunStyle;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.Tooltip;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
/**
* A Table representation of Transactions
*/
public class TransactionHistoryView extends FXViewPart
implements
IBlockchainView {
/**
* Important Note - This view is added to the list of registered blockchain
* views in the Activator. Because this class won't be initialized until
* user manually activate's the view. To avoid data loss this view is added
* in Activator
*/
/**
* These 2 are maintained as a static instance because FXViewPart creates
* one instance and we create another instance inactivator. This small
* glitch can be handled later
*/
private static TableView<TransactionModel> table;
/**
* A temporary model object
*/
private static Set<TransactionModel> tableContents = new HashSet<>();
/**
* {@inheritDoc}
*/
@Override
public void init(final IViewSite site) throws PartInitException {
super.init(site);
}
/**
* {@inheritDoc}
*/
@Override
protected Scene createFxScene() {
TransactionHistoryView.table = new TableView<>();
// Create the VBox
VBox root = new VBox(TransactionHistoryView.table);
TransactionHistoryView.table.setVisible(true);
TransactionHistoryView.table
.setPlaceholder(new Label("No transactions to display"));
TransactionHistoryView.table.setRowFactory(tv -> {
TableRow<TransactionModel> row = new TableRow<>();
row.setTooltip(new Tooltip("Double click to view details"));
row.setTextOverrun(OverrunStyle.ELLIPSIS);
row.setOnMouseClicked(event -> {
if ((event.getClickCount() == 2) && !row.isEmpty()) {
TransactionModel transaction = row.getItem();
String transactionDetailsMsg = "blockHash : "
+ transaction.getBlockHash()
+ System.lineSeparator() + "blockNumber : "
+ transaction.getBlockNumber()
+ System.lineSeparator() + "from : "
+ transaction.getFromAddress()
+ System.lineSeparator() + "gas : "
+ transaction.getGas() + System.lineSeparator()
+ "gasPrice : " + transaction.getGasPrice()
+ System.lineSeparator() + "hash : "
+ transaction.getTransactionHash()
+ System.lineSeparator() + "input : "
+ transaction.getInput() + System.lineSeparator()
+ "nonce : " + transaction.getNonce()
+ System.lineSeparator() + "r : "
+ transaction.getR() + System.lineSeparator()
+ "s : " + transaction.getS()
+ System.lineSeparator() + "to : "
+ transaction.getToAddress()
+ System.lineSeparator() + "transactionIndex : "
+ transaction.getTransactionIndex()
+ System.lineSeparator() + "v : "
+ transaction.getV() + System.lineSeparator()
+ "value : " + transaction.getValue()
+ System.lineSeparator();
showAlert(transactionDetailsMsg, "Transaction details");
}
});
return row;
});
TableColumn<TransactionModel, String> blockHashColumn = new TableColumn<>(
"Block Hash");
blockHashColumn
.setCellValueFactory(new PropertyValueFactory<>("blockHash"));
TableColumn<TransactionModel, String> blockNumberColumn = new TableColumn<>(
"block Number");
blockNumberColumn
.setCellValueFactory(new PropertyValueFactory<>("blockNumber"));
TableColumn<TransactionModel, String> fromAddressColumn = new TableColumn<>(
"From");
fromAddressColumn
.setCellValueFactory(new PropertyValueFactory<>("fromAddress"));
TableColumn<TransactionModel, String> gasColumn = new TableColumn<>(
"Gas");
gasColumn.setCellValueFactory(new PropertyValueFactory<>("gas"));
TableColumn<TransactionModel, String> gasPriceColumn = new TableColumn<>(
"Gas Price");
gasPriceColumn
.setCellValueFactory(new PropertyValueFactory<>("gasPrice"));
TableColumn<TransactionModel, String> transactionHashColumn = new TableColumn<>(
"Hash");
transactionHashColumn.setCellValueFactory(
new PropertyValueFactory<>("transactionHash"));
TableColumn<TransactionModel, String> inputColumn = new TableColumn<>(
"Input");
inputColumn.setCellValueFactory(new PropertyValueFactory<>("input"));
TableColumn<TransactionModel, String> nonceColumn = new TableColumn<>(
"Nonce");
nonceColumn.setCellValueFactory(new PropertyValueFactory<>("nonce"));
TableColumn<TransactionModel, String> rColumn = new TableColumn<>("R");
rColumn.setCellValueFactory(new PropertyValueFactory<>("r"));
TableColumn<TransactionModel, String> sColumn = new TableColumn<>("S");
sColumn.setCellValueFactory(new PropertyValueFactory<>("s"));
TableColumn<TransactionModel, String> toAddressColumn = new TableColumn<>(
"To");
toAddressColumn
.setCellValueFactory(new PropertyValueFactory<>("toAddress"));
TableColumn<TransactionModel, String> transactionIndexColumn = new TableColumn<>(
"Transaction Index");
transactionIndexColumn.setCellValueFactory(
new PropertyValueFactory<>("transactionIndex"));
TransactionHistoryView.table.getColumns().add(blockHashColumn);
TransactionHistoryView.table.getColumns().add(blockNumberColumn);
TransactionHistoryView.table.getColumns().add(fromAddressColumn);
TransactionHistoryView.table.getColumns().add(gasPriceColumn);
TransactionHistoryView.table.getColumns().add(transactionHashColumn);
TransactionHistoryView.table.getColumns().add(inputColumn);
TransactionHistoryView.table.getColumns().add(nonceColumn);
TransactionHistoryView.table.getColumns().add(rColumn);
TransactionHistoryView.table.getColumns().add(sColumn);
TransactionHistoryView.table.getColumns().add(toAddressColumn);
TransactionHistoryView.table.getColumns().add(transactionIndexColumn);
TransactionHistoryView.table.setTableMenuButtonVisible(true);
ContextMenu contextMenu = new ContextMenu();
MenuItem debugItem = new MenuItem("Debug");
MenuItem exportMenu = new MenuItem("Export");
MenuItem transactionReceiptMenu = new MenuItem("TX Receipt");
contextMenu.getItems().add(debugItem);
contextMenu.getItems().add(exportMenu);
contextMenu.getItems().add(transactionReceiptMenu);
transactionReceiptMenu.setOnAction((final ActionEvent event) -> {
try {
TransactionModel selectedItem = TransactionHistoryView.table
.getSelectionModel().getSelectedItem();
showAlert(
Web3jHandler.getInstance()
.getTransactionReceiptAsString(
selectedItem.getTransactionHash()),
"Transaction receipt");
} catch (IOException e) {
BlockchainCore.getInstance().logException(Activator.PLUGIN_ID,
"Error during transaction receipt generation", e);
}
});
TransactionHistoryView.table.setContextMenu(contextMenu);
TransactionHistoryView.table.autosize();
if (!tableContents.isEmpty()) {
TransactionHistoryView.table.getItems().addAll(tableContents);
}
// Create the Scene
Scene scene = new Scene(root);
scene.getStylesheets()
.add(getClass().getResource("Views.css").toExternalForm());
return scene;
}
private void showAlert(final String transactionDetailsMsg,
final String title) {
Alert transactionDetailsAlert = new Alert(AlertType.INFORMATION);
transactionDetailsAlert.setTitle(title);
TextArea detailsArea = new TextArea(transactionDetailsMsg);
detailsArea.setEditable(false);
detailsArea.setWrapText(true);
GridPane.setVgrow(detailsArea, Priority.ALWAYS);
GridPane.setHgrow(detailsArea, Priority.ALWAYS);
transactionDetailsAlert.getDialogPane()
.setExpandableContent(detailsArea);
transactionDetailsAlert.getDialogPane().setExpanded(true);
transactionDetailsAlert.showAndWait();
}
/**
* {@inheritDoc}
*/
@Override
protected void setFxFocus() {
}
/**
* {@inheritDoc}
*/
@Override
public void updateView(final TransactionModel transactionModel) {
tableContents.add(transactionModel);
if (TransactionHistoryView.table == null) {
return;// We are not supposed to manually create this let the
// framework handle the creation. data loss wont happen
// because we store the transaction in a set.
}
TransactionHistoryView.table.getItems().add(transactionModel);
TransactionHistoryView.table.refresh();
}
/**
* {@inheritDoc}
*/
@Override
public void dispose() {
super.dispose();
BlockchainViewsRegistry.dereisterBlockchainView(this);
}
}