package com.dgex.offspring.application.ui.statusbar; import java.text.SimpleDateFormat; import java.util.Date; import javax.annotation.PostConstruct; import javax.inject.Inject; import nxt.Block; import nxt.Nxt; import nxt.peer.Peer; import org.apache.log4j.Logger; import org.eclipse.e4.core.di.annotations.Optional; import org.eclipse.e4.ui.di.UIEventTopic; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.layout.PixelConverter; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import com.dgex.offspring.config.Formatter; import com.dgex.offspring.nxtCore.service.INxtService; public class StatusBar { static Logger logger = Logger.getLogger(StatusBar.class); private Composite mainComposite; private Composite messageGroup; private Composite progressGroup; private Composite peersGroup; private Composite blocksGroup; private Composite downloadsGroup; private Label messageText; private Label peersText; private Label blocksText; private Label downloadsText; private INxtService nxt; private ProgressIndicator progressIndicator; private PixelConverter pixelConverter; private final BlockchainDownloadMonitor downloadMonitor = new BlockchainDownloadMonitor(); static final String INITIALIZING_TEXT = "Initializing NXT " + Nxt.VERSION + " (might take several minutes)"; private String messageTextValue = INITIALIZING_TEXT; private Block lastBlock = null; private long messageTime = 0l; @PostConstruct public void postConstruct(Composite parent, INxtService _nxt, final Display display) { this.nxt = _nxt; mainComposite = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().numColumns(5).spacing(5, 0).margins(5, 5) .applyTo(mainComposite); pixelConverter = new PixelConverter(mainComposite); createContents(mainComposite); /* Display the block age each 1/5 th of second */ display.timerExec(200, new Runnable() { @Override public void run() { if (display != null && !display.isDisposed() && messageText != null && !messageText.isDisposed() && blocksText != null && !blocksText.isDisposed()) { if ((System.currentTimeMillis() - messageTime) < 2000) { messageText.setText(messageTextValue); } else if (lastBlock != null) { messageText.setText(createBlockAgeText(lastBlock)); } else { messageText.setText(""); } messageText.pack(); if (!downloadMonitor.isActive() && lastBlock != null) { downloadMonitor.blockPushed(lastBlock); } if (lastBlock != null) { blocksText.setText(createBlockText(lastBlock.getHeight(), 0)); blocksText.pack(); } mainComposite.layout(); display.timerExec(200, this); } } }); } private void createContents(Composite parent) { messageGroup = new Composite(parent, SWT.NONE); progressGroup = new Composite(parent, SWT.NONE); peersGroup = new Composite(parent, SWT.NONE); blocksGroup = new Composite(parent, SWT.NONE); downloadsGroup = new Composite(parent, SWT.NONE); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .grab(true, false).applyTo(messageGroup); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .hint(pixelConverter.convertHorizontalDLUsToPixels(130), SWT.DEFAULT) .applyTo(progressGroup); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(peersGroup); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(blocksGroup); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(downloadsGroup); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(messageGroup); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(progressGroup); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(peersGroup); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(blocksGroup); GridLayoutFactory.fillDefaults().numColumns(1).applyTo(downloadsGroup); messageText = new Label(messageGroup, SWT.NONE); messageText.setText(messageTextValue); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(messageText); progressIndicator = new ProgressIndicator(progressGroup); GridDataFactory.fillDefaults().grab(true, false) .align(SWT.FILL, SWT.BEGINNING).applyTo(progressIndicator); peersText = new Label(peersGroup, SWT.NONE); peersText.setText(createPeerText(0, 0, 0)); peersText.setToolTipText("Active peers / Known peers / Blacklisted peers"); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(peersText); downloadsText = new Label(downloadsGroup, SWT.NONE); downloadsText.setText(createDownloadsText(0, 0)); downloadsText.setToolTipText("Download volume / Upload volume"); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(downloadsText); blocksText = new Label(blocksGroup, SWT.NONE); blocksText.setText(createBlockText(0, 0)); blocksText.setToolTipText("Most recent block height"); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING) .applyTo(blocksText); downloadMonitor.setProgress(progressIndicator); } private void setStatusText(String message, boolean force) { messageTime = System.currentTimeMillis(); messageTextValue = message; if (force && messageText != null && !messageText.isDisposed()) { messageText.setText(messageTextValue); } } @Inject @Optional private void onInitializationStart( @UIEventTopic(INxtService.TOPIC_INITIALIZATION_START) int dummy) { setStatusText(INITIALIZING_TEXT, true); } @Inject @Optional private void onInitializationFinished( @UIEventTopic(INxtService.TOPIC_INITIALIZATION_FINISHED) int dummy) { setStatusText("Done", true); downloadMonitor.done(); } @Inject @Optional private void onLoggerMessage( @UIEventTopic(INxtService.TOPIC_LOGGER_MESSAGE) String message) { if (!nxt.isInitializing() && !nxt.isScanning()) { setStatusText(message, true); } } @Inject @Optional private void onLoggerException( @UIEventTopic(INxtService.TOPIC_LOGGER_EXCEPTION) Exception exception) { setStatusText("EXCEPTION >> " + exception, true); } @Inject @Optional private void onPeerEvent(@UIEventTopic(INxtService.TOPIC_PEER) Peer peer) { if (peersText != null && !peersText.isDisposed()) { int active = nxt.getAllConnectedPeers().size(); int known = nxt.getAllWellknownPeers().size(); int blacklisted = nxt.getAllBlacklistedPeers().size(); peersText.setText(createPeerText(active, known, blacklisted)); peersText.pack(); long downloadVolume = 0; long uploadVolume = 0; for (Peer p : nxt.getAllConnectedPeers()) { downloadVolume += p.getDownloadedVolume(); uploadVolume += p.getUploadedVolume(); } downloadsText.setText(createDownloadsText(downloadVolume, uploadVolume)); downloadsText.pack(); mainComposite.layout(); } } @Inject @Optional private void onBlockScanStart( @UIEventTopic(INxtService.TOPIC_BLOCK_SCANNER_START) int dummy) { setStatusText("Scanning blockchain", true); downloadMonitor.done(); } @Inject @Optional private void onBlockScanFinished( @UIEventTopic(INxtService.TOPIC_BLOCK_SCANNER_FINISHED) int dummy) { setStatusText("Scan complete", true); downloadMonitor.done(); } @Inject @Optional private void onBlockScanned( @UIEventTopic(INxtService.TOPIC_BLOCK_SCANNED) Block block) { lastBlock = block; downloadMonitor.blockPushed(block); } /* For each block pushed/poped we update the text in the blocks section */ @Inject @Optional private void onBlockPushed( @UIEventTopic(INxtService.TOPIC_BLOCK_PUSHED) Block block) { lastBlock = block; downloadMonitor.blockPushed(block); } @Inject @Optional private void onBlockPopped( @UIEventTopic(INxtService.TOPIC_BLOCK_POPPED) Block block) { lastBlock = block; } private String createPeerText(int active, int known, int blacklisted) { StringBuilder b = new StringBuilder(); // b.append(Messages.StatusBarToolControl_label_peers + " "); //$NON-NLS-2$ b.append(Integer.toString(active)); b.append("/"); //$NON-NLS-1$ b.append(Integer.toString(known)); b.append("/"); //$NON-NLS-1$ b.append(Integer.toString(blacklisted)); return b.toString(); } private String createBlockText(int height, int totalBlocks) { return Integer.toString(height); } private String createDownloadsText(long downloadVolume, long uploadVolume) { StringBuilder sb = new StringBuilder(); sb.append(Formatter.readableFileSize(downloadVolume)); sb.append("/"); sb.append(Formatter.readableFileSize(uploadVolume)); return sb.toString(); } private final SimpleDateFormat dateFormat = new SimpleDateFormat( "dd MMM yy H:mm:ss"); private String createBlockAgeText(Block block) { Date date = new Date(nxt.convertTimestamp(block.getTimestamp())); StringBuilder sb = new StringBuilder(); if (nxt.isScanning()) { sb.append("Scanning "); } else if ((System.currentTimeMillis() - date.getTime()) > 240 * 1000) { sb.append("Downloading "); } else { sb.append("Newest block "); } sb.append(dateFormat.format(date)); sb.append(" (" + ((new Date().getTime() - date.getTime()) / 1000) + " seconds)"); return sb.toString(); } }