package com.dgex.offspring.application.ui.accounts; import javax.xml.datatype.DatatypeConfigurationException; import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.Duration; import nxt.Generator; import org.apache.log4j.Logger; import org.eclipse.e4.ui.services.IStylingEngine; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import com.dgex.offspring.application.utils.Layouts; import com.dgex.offspring.config.CSSClasses; import com.dgex.offspring.config.Clipboards; import com.dgex.offspring.messages.Messages; import com.dgex.offspring.nxtCore.service.INxtService; import com.dgex.offspring.ui.SendMessageWizard; import com.dgex.offspring.ui.SendMoneyWizard; import com.dgex.offspring.user.service.IUser; import com.dgex.offspring.user.service.IUserService; import com.dgex.offspring.wallet.IWallet; import com.dgex.offspring.wallet.IWallet.AccountNotFoundException; import com.dgex.offspring.wallet.IWallet.WalletBackupException; import com.dgex.offspring.wallet.IWallet.WalletNotInitializedException; import com.dgex.offspring.wallet.IWalletAccount; import com.dgex.offspring.wallet.NXTAccount; public class AccountButtonComposite extends Composite { private final Logger logger = Logger.getLogger(AccountButtonComposite.class); private final Link nameLabel; private final Label accountLabel; private final Label balanceLabel; private Button forgeButton; private IUser user; private boolean isActive = false; private String selectedNameLabel; private String normalNameLabel; private long deadline = Long.MAX_VALUE; public AccountButtonComposite(final Composite parent, final IUser user, final IUserService userService, final IWallet wallet, IStylingEngine engine, final INxtService nxt) { super(parent, SWT.NONE); this.user = user; initializeCroppedNames(user.getName(), engine); setLayout(Layouts.Grid.create(1, 0, 12, 5, 0, 0, 2)); engine.setClassname(this, CSSClasses.ACCOUNTBUTTON); nameLabel = new Link(this, SWT.NONE); nameLabel.setText("<A>" + normalNameLabel + "</A>"); //$NON-NLS-1$ //$NON-NLS-2$ nameLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); nameLabel.setToolTipText(Messages.AccountButtonComposite_label_right_click); nameLabel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { userService.setActiveUser(user); } }); engine.setClassname(nameLabel, CSSClasses.ACCOUNT_LABEL); accountLabel = new Label(this, SWT.NONE); accountLabel.setText(user.getAccount().getStringId()); accountLabel .setToolTipText(Messages.AccountButtonComposite_label_right_click); accountLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); engine.setClassname(accountLabel, CSSClasses.ACCOUNT_NUMBER); balanceLabel = new Label(this, SWT.NONE); balanceLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false)); balanceLabel .setToolTipText(Messages.AccountButtonComposite_label_right_click + " - account balance based on 42 confirmations"); engine.setClassname(balanceLabel, CSSClasses.ACCOUNT_BALANCE); forgeButton = new Button(this, SWT.CHECK); forgeButton.setSelection(user.getAccount().isForging()); forgeButton.setText("Forge"); forgeButton.setEnabled(!user.getAccount().isReadOnly()); forgeButton .setToolTipText("Block generation deadline is estimated, actual deadline may vary"); forgeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (forgeButton.getSelection()) { if (!user.getAccount().startForging()) { forgeButton.removeSelectionListener(this); forgeButton.setSelection(false); forgeButton.setText("Forge"); forgeButton.addSelectionListener(this); } } else { user.getAccount().stopForging(); forgeButton.setText("Forge"); } } }); setBalance(0l, 0l); Menu menu = new Menu(parent.getShell(), SWT.POP_UP); nameLabel.setMenu(menu); balanceLabel.setMenu(menu); accountLabel.setMenu(menu); MenuItem item = new MenuItem(menu, SWT.PUSH); item.setText("Send money"); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Shell shell = getShell(); if (shell != null) { while (shell.getParent() != null) { shell = shell.getParent().getShell(); } } WizardDialog dialog = new WizardDialog(shell, new SendMoneyWizard( userService, nxt, user.getAccount().getId())); dialog.open(); } }); item = new MenuItem(menu, SWT.PUSH); item.setText("Send Encrypted Message"); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Shell shell = getShell(); if (shell != null) { while (shell.getParent() != null) { shell = shell.getParent().getShell(); } } WizardDialog dialog = new WizardDialog(shell, new SendMessageWizard( userService, nxt, user.getAccount().getId(), null, true)); dialog.open(); } }); item = new MenuItem(menu, SWT.PUSH); item.setText("Send Plain Message"); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Shell shell = getShell(); if (shell != null) { while (shell.getParent() != null) { shell = shell.getParent().getShell(); } } WizardDialog dialog = new WizardDialog(shell, new SendMessageWizard( userService, nxt, user.getAccount().getId(), null, false)); dialog.open(); } }); item = new MenuItem(menu, SWT.PUSH); item.setText(Messages.AccountButtonComposite_label_copy_account_number); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Clipboards.copy(parent.getDisplay(), user.getAccount().getStringId()); } }); item = new MenuItem(menu, SWT.PUSH); item.setText(Messages.AccountButtonComposite_label_copy_private_key); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Clipboards.copy(parent.getDisplay(), user.getAccount().getPrivateKey()); } }); item = new MenuItem(menu, SWT.PUSH); item.setText(Messages.AccountButtonComposite_label_copy_balance); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Clipboards.copy(parent.getDisplay(), Long.toString(user.getAccount().getBalance())); } }); item = new MenuItem(menu, SWT.PUSH); item.setText(Messages.AccountButtonComposite_label_copy_account_label); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Clipboards.copy(parent.getDisplay(), user.getName()); } }); item = new MenuItem(menu, SWT.PUSH); item.setText(Messages.AccountButtonComposite_label_remove_account); item.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { if (!MessageDialog.openConfirm(getShell(), Messages.AccountButtonComposite_confirm_remove_dialog_title, Messages.AccountButtonComposite_confirm_remove_dialog_message)) return; IWalletAccount walletAccount = NXTAccount.create(user.getName(), user .getAccount().getStringId(), user.getAccount().getPrivateKey(), user.getAccount().getBalance()); try { wallet.removeAccount(walletAccount); boolean active = user.equals(userService.getActiveUser()); userService.removeUser(user); if (active && userService.getUsers().size() > 0) userService.setActiveUser(userService.getUsers().get(0)); } catch (WalletNotInitializedException e) { logger.error("Not initialized", e); //$NON-NLS-1$ } catch (AccountNotFoundException e) { logger.error("Account not found", e); //$NON-NLS-1$ } catch (WalletBackupException e) { logger.error("Backup error", e); //$NON-NLS-1$ } } }); pack(); layout(); } @Override public void dispose() { this.user = null; super.dispose(); } public IUser getUser() { return user; } public void setBalance(Long balance, Long unconfirmedBalance) { String text = "NXT "; if ((unconfirmedBalance - balance) > 1 || (unconfirmedBalance - balance) < -1) text += Long.toString(balance) + " (" + Long.toString(unconfirmedBalance) + ")"; else text += Long.toString(balance); balanceLabel.setText(text); layout(); } public void setActive(boolean active) { if (active != isActive) { isActive = active; nameLabel.setText("<A>" + (active ? selectedNameLabel : normalNameLabel) //$NON-NLS-1$ + "</A>"); //$NON-NLS-1$ nameLabel.pack(); } } public void setGeneratorDeadline(long deadline) { this.deadline = System.currentTimeMillis() + (deadline * 1000); } public void startForging(Generator generator) { if (forgeButton.getSelection() == false) { forgeButton.setSelection(true); } } public void stopForging(Generator generator) { if (forgeButton.getSelection() == true) { forgeButton.setSelection(false); } } public void updateGenerationDeadline() { if (forgeButton == null || forgeButton.isDisposed() || deadline == Long.MAX_VALUE) return; long remaining = deadline - System.currentTimeMillis(); String text = "Forge"; if (user.getAccount().isForging()) { if (remaining < 0) { text = "Forge in unknown"; } else { Duration duration; try { duration = DatatypeFactory.newInstance().newDuration(remaining); text = "Forge in " + String.format("%dh:%dm:%ds", duration.getDays() * 24 + duration.getHours(), duration.getMinutes(), duration.getSeconds()); } catch (DatatypeConfigurationException e) { logger.error("Not able to format deadline", e); } } } forgeButton.setText(text); forgeButton.pack(); forgeButton.getParent().layout(); } /* Calculates the text for name and selected name (with a > in front) */ private void initializeCroppedNames(String name, IStylingEngine engine) { /* Maximum length of an account number is 22 */ Label label = new Label(this, SWT.NONE); engine.setClassname(label, CSSClasses.ACCOUNT_NUMBER); GC gc = new GC(label); Point size = gc.textExtent("0000000000000000000000"); //$NON-NLS-1$ gc.dispose(); label.dispose(); int maxWidth = size.x; Link link = new Link(this, SWT.NONE); engine.setClassname(link, CSSClasses.ACCOUNT_LABEL); gc = new GC(link); /* Calculate text for selected account */ String text = "> " + name; //$NON-NLS-1$ for (int i = text.length(); i >= 1; i--) { size = gc.textExtent(text); if (size.x > maxWidth) text = text.substring(0, text.length() - 2); else break; } selectedNameLabel = text; /* Calculate the text for none selected account */ text = name; for (int i = text.length(); i >= 1; i--) { size = gc.textExtent(text); if (size.x > maxWidth) text = text.substring(0, text.length() - 2); else break; } normalNameLabel = text; gc.dispose(); link.dispose(); } };