package gui.assets; import gui.BalanceRenderer; import gui.models.BalancesComboBoxModel; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Insets; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import javax.swing.*; import javax.swing.border.EmptyBorder; import org.mapdb.Fun.Tuple2; import controller.Controller; import database.SortableList; import qora.account.Account; import qora.assets.Asset; import qora.payment.Payment; import utils.Pair; @SuppressWarnings("serial") public class PayDividendFrame extends JFrame { private Asset asset; private JTextField txtAsset; private JTextField txtAccount; private JComboBox<Pair<Tuple2<String, Long>, BigDecimal>> cbxAssetToPay; private JTextField txtAmount; private JTextField txtHolders; private JButton generateButton; public PayDividendFrame(Asset asset) { super("Qora - Pay Dividend"); this.asset = asset; //CLOSE setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //ICON List<Image> icons = new ArrayList<Image>(); icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon16.png")); icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon32.png")); icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon64.png")); icons.add(Toolkit.getDefaultToolkit().getImage("images/icons/icon128.png")); this.setIconImages(icons); //LAYOUT this.setLayout(new GridBagLayout()); //PADDING ((JComponent) this.getContentPane()).setBorder(new EmptyBorder(5, 5, 5, 5)); //LABEL GBC GridBagConstraints labelGBC = new GridBagConstraints(); labelGBC.insets = new Insets(5,5,5,5); labelGBC.fill = GridBagConstraints.HORIZONTAL; labelGBC.anchor = GridBagConstraints.NORTHWEST; labelGBC.weightx = 0; labelGBC.gridx = 0; //COMBOBOX GBC GridBagConstraints cbxGBC = new GridBagConstraints(); cbxGBC.insets = new Insets(5,5,5,5); cbxGBC.fill = GridBagConstraints.NONE; cbxGBC.anchor = GridBagConstraints.NORTHWEST; cbxGBC.weightx = 0; cbxGBC.gridx = 1; //TEXTFIELD GBC GridBagConstraints txtGBC = new GridBagConstraints(); txtGBC.insets = new Insets(5,5,5,5); txtGBC.fill = GridBagConstraints.HORIZONTAL; txtGBC.anchor = GridBagConstraints.NORTHWEST; txtGBC.weightx = 1; txtGBC.gridwidth = 2; txtGBC.gridx = 1; //BUTTON GBC GridBagConstraints buttonGBC = new GridBagConstraints(); buttonGBC.insets = new Insets(5,5,5,5); buttonGBC.fill = GridBagConstraints.NONE; buttonGBC.anchor = GridBagConstraints.NORTHWEST; buttonGBC.gridwidth = 2; buttonGBC.gridx = 0; //LABEL ASSET labelGBC.gridy = 0; JLabel assetLabel = new JLabel("Asset:"); this.add(assetLabel, labelGBC); //TXT ASSET txtGBC.gridy = 0; this.txtAsset = new JTextField(asset.toString()); this.txtAsset.setEditable(false); this.add(this.txtAsset, txtGBC); //LABEL ACCOUNT labelGBC.gridy = 1; JLabel accountLabel = new JLabel("Account:"); this.add(accountLabel, labelGBC); //TXT ACCOUNT txtGBC.gridy = 1; this.txtAccount = new JTextField(asset.getOwner().getAddress()); this.txtAccount.setEditable(false); this.add(this.txtAccount, txtGBC); //LABEL ASSET TO PAY labelGBC.gridy = 2; JLabel AssetToPayLabel = new JLabel("Asset to pay:"); this.add(AssetToPayLabel, labelGBC); //CBX ASSET TO PAY txtGBC.gridy = 2; this.cbxAssetToPay = new JComboBox<Pair<Tuple2<String, Long>, BigDecimal>>(new BalancesComboBoxModel(asset.getOwner())); this.cbxAssetToPay.setRenderer(new BalanceRenderer()); this.add(this.cbxAssetToPay, txtGBC); //LABEL AMOUNT labelGBC.gridy = 3; JLabel amountLabel = new JLabel("Amount to pay:"); this.add(amountLabel, labelGBC); //TXT AMOUNT txtGBC.gridy = 3; this.txtAmount = new JTextField(); this.txtAmount.setText("1"); this.add(this.txtAmount, txtGBC); //LABEL HOLDERS TO PAY labelGBC.gridy = 4; JLabel holdersToPayLabel = new JLabel("Holders to pay (1-400):"); this.add(holdersToPayLabel, labelGBC); //TXT QUANTITY txtGBC.gridy = 4; this.txtHolders = new JTextField(); this.txtHolders.setText("1"); this.add(this.txtHolders, txtGBC); //BUTTON GENERATE buttonGBC.gridy = 5; this.generateButton = new JButton("Generate Payment"); this.generateButton.setPreferredSize(new Dimension(160, 25)); this.generateButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { onGenerateClick(); } }); this.add(this.generateButton, buttonGBC); //PACK this.pack(); this.setResizable(false); this.setLocationRelativeTo(null); this.setVisible(true); } @SuppressWarnings("unchecked") public void onGenerateClick() { int parsing = 0; try { //HOLDERS TO PAY parsing = 1; int holders = Integer.parseInt(this.txtHolders.getText()); //AMOUNT TO PAY parsing = 2; BigDecimal amount = new BigDecimal(txtAmount.getText()).setScale(8); //ASSET TO PAY long assetKey = ((Pair<Tuple2<String, Long>, BigDecimal>) this.cbxAssetToPay.getSelectedItem()).getA().b; Asset assetToPay = Controller.getInstance().getAsset(assetKey); //BALANCES SortableList<Tuple2<String, Long>, BigDecimal> balances = Controller.getInstance().getBalances(this.asset.getKey()); //GET ACCOUNTS AND THEIR TOTAL BALANCE List<Account> accounts = new ArrayList<Account>(); BigDecimal total = BigDecimal.ZERO.setScale(8); for(int i=0; i<holders && i<balances.size(); i++) { Account account = new Account(balances.get(i).getA().a); accounts.add(account); total = total.add(balances.get(i).getB()); } //CREATE PAYMENTS List<Payment> payments = new ArrayList<Payment>(); for(Account account: accounts) { //CALCULATE PERCENTAGE OF TOTAL BigDecimal percentage = account.getConfirmedBalance(this.asset.getKey()).divide(total, 8, RoundingMode.DOWN); //CALCULATE AMOUNT BigDecimal accountAmount = amount.multiply(percentage); //ROUND AMOUNT if(assetToPay.isDivisible()) { accountAmount = accountAmount.setScale(8, RoundingMode.DOWN); } else { accountAmount = accountAmount.setScale(0, RoundingMode.DOWN).setScale(8); } //CHECK IF AMOUNT NOT ZERO if(accountAmount.compareTo(BigDecimal.ZERO) > 0) { Payment payment = new Payment(account, assetToPay.getKey(), accountAmount); payments.add(payment); } } new MultiPaymentFrame(this.asset, payments); } catch(Exception e) { //CHECK WHERE PARSING ERROR HAPPENED switch(parsing) { case 1: JOptionPane.showMessageDialog(new JFrame(), "Invalid holders to pay!", "Error", JOptionPane.ERROR_MESSAGE); break; case 2: JOptionPane.showMessageDialog(new JFrame(), "Invalid amount to pay!", "Error", JOptionPane.ERROR_MESSAGE); break; } } } }