add settings, arbitration selection, arb. registration, change setup, change funding, manage keys in wallet

This commit is contained in:
Manfred Karrer 2014-06-18 21:48:40 +02:00
parent 64f88a9ea2
commit a03c24d664
82 changed files with 5847 additions and 744 deletions

Binary file not shown.

View file

@ -1,22 +1,19 @@
package io.bitsquare; package io.bitsquare;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Utils;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.WalletFacade;
import io.bitsquare.di.BitSquareModule; import io.bitsquare.di.BitSquareModule;
import io.bitsquare.di.GuiceFXMLLoader; import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.util.Localisation; import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.settings.Settings; import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage; import io.bitsquare.storage.Storage;
import io.bitsquare.user.Arbitrator; import io.bitsquare.user.Arbitrator;
import io.bitsquare.user.Reputation;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.DSAKeyUtil; import io.bitsquare.util.DSAKeyUtil;
import io.bitsquare.util.MockData;
import javafx.application.Application; import javafx.application.Application;
import javafx.scene.Parent; import javafx.scene.Parent;
import javafx.scene.Scene; import javafx.scene.Scene;
@ -24,15 +21,16 @@ import javafx.stage.Stage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.security.KeyPair; import java.io.IOException;
import java.security.KeyPairGenerator; import java.util.ArrayList;
import java.security.PublicKey; import java.util.List;
import java.util.Locale; import java.util.Locale;
public class BitSquare extends Application public class BitSquare extends Application
{ {
private static final Logger log = LoggerFactory.getLogger(BitSquare.class); private static final Logger log = LoggerFactory.getLogger(BitSquare.class);
public static String ID = "bitsquare"; public static String ID = "bitsquare";
private static Stage stage;
private WalletFacade walletFacade; private WalletFacade walletFacade;
private MessageFacade messageFacade; private MessageFacade messageFacade;
@ -48,6 +46,7 @@ public class BitSquare extends Application
@Override @Override
public void start(Stage stage) throws Exception public void start(Stage stage) throws Exception
{ {
BitSquare.stage = stage;
log.debug("Startup: start"); log.debug("Startup: start");
final Injector injector = Guice.createInjector(new BitSquareModule()); final Injector injector = Guice.createInjector(new BitSquareModule());
walletFacade = injector.getInstance(WalletFacade.class); walletFacade = injector.getInstance(WalletFacade.class);
@ -62,7 +61,8 @@ public class BitSquare extends Application
user.updateFromStorage((User) storage.read(user.getClass().getName())); user.updateFromStorage((User) storage.read(user.getClass().getName()));
// mock // mock
initSettings(settings, storage, user); //initSettings(settings, storage, user);
settings.updateFromStorage((Settings) storage.read(settings.getClass().getName())); settings.updateFromStorage((Settings) storage.read(settings.getClass().getName()));
@ -89,6 +89,46 @@ public class BitSquare extends Application
stage.show(); stage.show();
log.debug("Startup: stage displayed"); log.debug("Startup: stage displayed");
addMockArbitrator();
}
private void addMockArbitrator()
{
String pubKeyAsHex = walletFacade.getArbitratorPubKeyAsHex();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
List<Locale> languages = new ArrayList<>();
languages.add(LanguageUtil.getDefaultLanguageLocale());
List<Arbitrator.METHODS> arbitrationMethods = new ArrayList<>();
arbitrationMethods.add(Arbitrator.METHODS.TLS_NOTARY);
List<Arbitrator.ID_VERIFICATIONS> idVerifications = new ArrayList<>();
idVerifications.add(Arbitrator.ID_VERIFICATIONS.PASSPORT);
idVerifications.add(Arbitrator.ID_VERIFICATIONS.GOV_ID);
Arbitrator arbitrator = new Arbitrator(pubKeyAsHex,
messagePubKeyAsHex,
"Manfred Karrer",
Arbitrator.ID_TYPE.REAL_LIFE_ID,
languages,
new Reputation(),
1,
0.01,
0.001,
10,
0.1,
arbitrationMethods,
idVerifications,
"http://bitsquare.io/",
"Bla bla..."
);
try
{
messageFacade.addArbitrator(arbitrator);
} catch (IOException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
} }
@Override @Override
@ -100,24 +140,29 @@ public class BitSquare extends Application
super.stop(); super.stop();
} }
private void initSettings(Settings settings, Storage storage, User user) public static Stage getStage()
{
return stage;
}
/* private void initSettings(Settings settings, Storage storage, User user)
{ {
Settings savedSettings = (Settings) storage.read(settings.getClass().getName()); Settings savedSettings = (Settings) storage.read(settings.getClass().getName());
if (savedSettings == null) if (savedSettings == null)
{ {
// write default settings // write default settings
settings.getAcceptedCountryLocales().clear(); settings.getAcceptedCountries().clear();
// settings.addAcceptedLanguageLocale(Locale.getDefault()); // settings.addAcceptedLanguageLocale(Locale.getDefault());
settings.addAcceptedLanguageLocale(MockData.getLocales().get(0)); settings.addAcceptedLanguageLocale(MockData.getLocales().get(0));
settings.addAcceptedLanguageLocale(new Locale("en", "US")); settings.addAcceptedLanguageLocale(new Locale("en", "US"));
settings.addAcceptedLanguageLocale(new Locale("es", "ES")); settings.addAcceptedLanguageLocale(new Locale("es", "ES"));
settings.getAcceptedCountryLocales().clear(); settings.getAcceptedCountries().clear();
//settings.addAcceptedCountryLocale(Locale.getDefault()); //settings.addAcceptedCountry(Locale.getDefault());
settings.addAcceptedCountryLocale(MockData.getLocales().get(0)); settings.addAcceptedCountry(MockData.getLocales().get(0));
settings.addAcceptedCountryLocale(new Locale("en", "US")); settings.addAcceptedCountry(new Locale("en", "US"));
settings.addAcceptedCountryLocale(new Locale("de", "DE")); settings.addAcceptedCountry(new Locale("de", "DE"));
settings.addAcceptedCountryLocale(new Locale("es", "ES")); settings.addAcceptedCountry(new Locale("es", "ES"));
settings.getAcceptedArbitrators().clear(); settings.getAcceptedArbitrators().clear();
@ -137,9 +182,9 @@ public class BitSquare extends Application
//initMockUser(storage, user); //initMockUser(storage, user);
} }
} } */
private String getMessagePubKey() /* private String getMessagePubKey()
{ {
try try
{ {
@ -152,10 +197,10 @@ public class BitSquare extends Application
{ {
return null; return null;
} }
} } */
private void initMockUser(Storage storage, User user) /* private void initMockUser(Storage storage, User user)
{ {
user.getBankAccounts().clear(); user.getBankAccounts().clear();
@ -182,5 +227,5 @@ public class BitSquare extends Application
user.setAccountID(Utils.bytesToHexString(new ECKey().getPubKey())); user.setAccountID(Utils.bytesToHexString(new ECKey().getPubKey()));
storage.write(user.getClass().getName(), user); storage.write(user.getClass().getName(), user);
} } */
} }

View file

@ -1,42 +1,60 @@
package io.bitsquare.bank; package io.bitsquare.bank;
import io.bitsquare.locale.Country;
import java.io.Serializable; import java.io.Serializable;
import java.util.Currency; import java.util.Currency;
import java.util.Locale; import java.util.Objects;
public class BankAccount implements Serializable public class BankAccount implements Serializable
{ {
private static final long serialVersionUID = 1792577576443221268L; private static final long serialVersionUID = 1792577576443221268L;
private BankAccountType bankAccountType; private BankAccountTypeInfo bankAccountTypeInfo;
private String accountPrimaryID; private String accountPrimaryID;
private String accountSecondaryID; private String accountSecondaryID;
private String accountHolderName; private String accountHolderName;
private Locale countryLocale; private Country country;
private Currency currency; private Currency currency;
private String uid; private String uid;
private String accountTitle; private String accountTitle;
public BankAccount(BankAccountType bankAccountType, public BankAccount(BankAccountTypeInfo bankAccountTypeInfo,
Currency currency, Currency currency,
Locale countryLocale, Country country,
String accountTitle, String accountTitle,
String accountHolderName, String accountHolderName,
String accountPrimaryID, String accountPrimaryID,
String accountSecondaryID) String accountSecondaryID)
{ {
this.bankAccountType = bankAccountType; this.bankAccountTypeInfo = bankAccountTypeInfo;
this.currency = currency; this.currency = currency;
this.countryLocale = countryLocale; this.country = country;
this.accountTitle = accountTitle; this.accountTitle = accountTitle;
this.accountHolderName = accountHolderName; this.accountHolderName = accountHolderName;
this.accountPrimaryID = accountPrimaryID; this.accountPrimaryID = accountPrimaryID;
this.accountSecondaryID = accountSecondaryID; this.accountSecondaryID = accountSecondaryID;
uid = bankAccountType + "_" + accountPrimaryID + "_" + accountSecondaryID + "_" + accountHolderName + "_" + countryLocale.getCountry(); uid = accountTitle;
}
public int hashCode()
{
return Objects.hashCode(uid);
}
public boolean equals(Object obj)
{
if (!(obj instanceof BankAccount))
return false;
if (obj == this)
return true;
BankAccount other = (BankAccount) obj;
return other.getUid().equals(uid);
} }
public String getAccountPrimaryID() public String getAccountPrimaryID()
@ -54,9 +72,9 @@ public class BankAccount implements Serializable
return accountHolderName; return accountHolderName;
} }
public BankAccountType getBankAccountType() public BankAccountTypeInfo getBankAccountTypeInfo()
{ {
return bankAccountType; return bankAccountTypeInfo;
} }
public Currency getCurrency() public Currency getCurrency()
@ -64,9 +82,9 @@ public class BankAccount implements Serializable
return currency; return currency;
} }
public Locale getCountryLocale() public Country getCountry()
{ {
return countryLocale; return country;
} }
public String getUid() public String getUid()
@ -83,11 +101,11 @@ public class BankAccount implements Serializable
public String toString() public String toString()
{ {
return "BankAccount{" + return "BankAccount{" +
"bankAccountType=" + bankAccountType + "bankAccountType=" + bankAccountTypeInfo.getType() +
", accountPrimaryID='" + accountPrimaryID + '\'' + ", accountPrimaryID='" + accountPrimaryID + '\'' +
", accountSecondaryID='" + accountSecondaryID + '\'' + ", accountSecondaryID='" + accountSecondaryID + '\'' +
", accountHolderName='" + accountHolderName + '\'' + ", accountHolderName='" + accountHolderName + '\'' +
", countryLocale=" + countryLocale + ", countryLocale=" + country +
", currency=" + currency + ", currency=" + currency +
", uid='" + uid + '\'' + ", uid='" + uid + '\'' +
", accountTitle='" + accountTitle + '\'' + ", accountTitle='" + accountTitle + '\'' +

View file

@ -1,48 +0,0 @@
package io.bitsquare.bank;
import java.io.Serializable;
public class BankAccountType implements Serializable
{
private static final long serialVersionUID = -8772708150197835288L;
public static enum BankAccountTypeEnum
{
SEPA, WIRE, INTERNATIONAL, OK_PAY, NET_TELLER, PERFECT_MONEY, OTHER
}
private BankAccountTypeEnum type;
private String primaryIDName;
private String secondaryIDName;
public BankAccountType(BankAccountTypeEnum type, String primaryIDName, String secondaryIDName)
{
this.type = type;
this.primaryIDName = primaryIDName;
this.secondaryIDName = secondaryIDName;
}
public BankAccountTypeEnum getType()
{
return type;
}
public String getPrimaryIDName()
{
return primaryIDName;
}
public String getSecondaryIDName()
{
return secondaryIDName;
}
@Override
public String toString()
{
//TODO localisation
return type.toString();
}
}

View file

@ -0,0 +1,71 @@
package io.bitsquare.bank;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Objects;
public class BankAccountTypeInfo implements Serializable
{
private static final long serialVersionUID = -8772708150197835288L;
public static enum BankAccountType
{
SEPA, WIRE, INTERNATIONAL, OK_PAY, NET_TELLER, PERFECT_MONEY, OTHER
}
public static ArrayList<BankAccountTypeInfo> getAllBankAccountTypeInfoObjects()
{
ArrayList<BankAccountTypeInfo> bankTransferTypes = new ArrayList<>();
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.SEPA, "IBAN", "BIC"));
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.WIRE, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.INTERNATIONAL, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.OK_PAY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.NET_TELLER, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.PERFECT_MONEY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountTypeInfo(BankAccountType.OTHER, "Prim_todo", "Sec_todo"));
return bankTransferTypes;
}
private BankAccountType type;
private String primaryIDName;
private String secondaryIDName;
public BankAccountTypeInfo(BankAccountType type, String primaryIDName, String secondaryIDName)
{
this.type = type;
this.primaryIDName = primaryIDName;
this.secondaryIDName = secondaryIDName;
}
public int hashCode()
{
return Objects.hashCode(type);
}
public boolean equals(Object obj)
{
if (!(obj instanceof BankAccountTypeInfo))
return false;
if (obj == this)
return true;
BankAccountTypeInfo other = (BankAccountTypeInfo) obj;
return other.getType().equals(type);
}
public BankAccountType getType()
{
return type;
}
public String getPrimaryIDName()
{
return primaryIDName;
}
public String getSecondaryIDName()
{
return secondaryIDName;
}
}

View file

@ -0,0 +1,27 @@
package io.bitsquare.btc;
import com.google.bitcoin.core.Address;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigInteger;
public class BalanceListener
{
private static final Logger log = LoggerFactory.getLogger(BalanceListener.class);
private Address address;
public BalanceListener(Address address)
{
this.address = address;
}
public Address getAddress()
{
return address;
}
public void onBalanceChanged(BigInteger balance)
{
}
}

View file

@ -1,8 +1,8 @@
package io.bitsquare.btc; package io.bitsquare.btc;
import com.google.bitcoin.core.Utils; import com.google.bitcoin.core.Utils;
import io.bitsquare.gui.util.Converter; import io.bitsquare.gui.util.BitSquareConverter;
import io.bitsquare.gui.util.Formatter; import io.bitsquare.gui.util.BitSquareFormatter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -25,7 +25,7 @@ public class BtcFormatter
public static BigInteger stringValueToSatoshis(String value) public static BigInteger stringValueToSatoshis(String value)
{ {
return Utils.toNanoCoins(String.valueOf(Converter.stringToDouble(value))); return Utils.toNanoCoins(String.valueOf(BitSquareConverter.stringToDouble2(value)));
} }
public static BigInteger doubleValueToSatoshis(double value) public static BigInteger doubleValueToSatoshis(double value)
@ -48,8 +48,8 @@ public class BtcFormatter
public static String formatSatoshis(BigInteger satoshis, boolean useBTC) public static String formatSatoshis(BigInteger satoshis, boolean useBTC)
{ {
if (useBTC) if (useBTC)
return Formatter.formatDouble(satoshiToBTC(satoshis), 8) + " BTC"; return BitSquareFormatter.formatDouble(satoshiToBTC(satoshis), 8) + " BTC";
else else
return Formatter.formatDouble(satoshiToBTC(satoshis), 8); return BitSquareFormatter.formatDouble(satoshiToBTC(satoshis), 8);
} }
} }

View file

@ -0,0 +1,28 @@
package io.bitsquare.btc;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.TransactionConfidence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ConfidenceListener
{
private static final Logger log = LoggerFactory.getLogger(ConfidenceListener.class);
private Address address;
public ConfidenceListener(Address address)
{
this.address = address;
}
public Address getAddress()
{
return address;
}
public void onTransactionConfidenceChanged(TransactionConfidence confidence)
{
}
}

View file

@ -7,6 +7,7 @@ import com.google.bitcoin.params.MainNetParams;
import com.google.bitcoin.params.RegTestParams; import com.google.bitcoin.params.RegTestParams;
import com.google.bitcoin.script.Script; import com.google.bitcoin.script.Script;
import com.google.bitcoin.script.ScriptBuilder; import com.google.bitcoin.script.ScriptBuilder;
import com.google.bitcoin.script.ScriptOpCodes;
import com.google.bitcoin.utils.Threading; import com.google.bitcoin.utils.Threading;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
@ -21,9 +22,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN; import static com.google.bitcoin.script.ScriptOpCodes.OP_RETURN;
@ -45,8 +44,10 @@ public class WalletFacade
private List<DownloadListener> downloadListeners = new ArrayList<>(); private List<DownloadListener> downloadListeners = new ArrayList<>();
private Wallet wallet; private Wallet wallet;
private ECKey registrationKey; private ECKey arbitratorKey;
private ECKey tradingKey; private WalletEventListener walletEventListener;
private List<ConfidenceListener> confidenceListeners = new ArrayList<>();
private List<BalanceListener> balanceListeners = new ArrayList<>();
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -100,9 +101,6 @@ public class WalletFacade
wallet = walletAppKit.wallet(); wallet = walletAppKit.wallet();
registrationKey = wallet.getKeys().get(0);
tradingKey = new ECKey();
wallet.addKey(tradingKey);
wallet.allowSpendingUnconfirmedTransactions(); wallet.allowSpendingUnconfirmedTransactions();
//walletAppKit.peerGroup().setMaxConnections(11); //walletAppKit.peerGroup().setMaxConnections(11);
@ -111,6 +109,49 @@ public class WalletFacade
walletAppKit.peerGroup().setMinBroadcastConnections(1); walletAppKit.peerGroup().setMinBroadcastConnections(1);
/* else /* else
walletAppKit.peerGroup().setMinBroadcastConnections(2); */ walletAppKit.peerGroup().setMinBroadcastConnections(2); */
walletEventListener = new WalletEventListener()
{
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
notifyBalanceListeners(tx);
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
notifyConfidenceListeners(tx);
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
notifyBalanceListeners(tx);
}
@Override
public void onReorganize(Wallet wallet)
{
}
@Override
public void onWalletChanged(Wallet wallet)
{
}
@Override
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
{
}
@Override
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
}
};
wallet.addEventListener(walletEventListener);
} }
public void shutDown() public void shutDown()
@ -134,6 +175,189 @@ public class WalletFacade
downloadListeners.remove(listener); downloadListeners.remove(listener);
} }
public void addConfidenceListener(ConfidenceListener listener)
{
confidenceListeners.add(listener);
}
public void removeConfidenceListener(ConfidenceListener listener)
{
confidenceListeners.remove(listener);
}
public void addBalanceListener(BalanceListener listener)
{
balanceListeners.add(listener);
}
public void removeBalanceListener(BalanceListener listener)
{
balanceListeners.remove(listener);
}
private void notifyConfidenceListeners(Transaction tx)
{
for (int i = 0; i < confidenceListeners.size(); i++)
{
ConfidenceListener confidenceListener = confidenceListeners.get(i);
List<TransactionOutput> transactionOutputs = tx.getOutputs();
for (int n = 0; n < transactionOutputs.size(); n++)
{
TransactionOutput transactionOutput = transactionOutputs.get(n);
if (!isOpReturnScript(transactionOutput))
{
Address address = transactionOutput.getScriptPubKey().getToAddress(params);
if (address.equals(confidenceListener.getAddress()))
{
confidenceListener.onTransactionConfidenceChanged(tx.getConfidence());
}
}
}
}
}
private boolean isOpReturnScript(TransactionOutput transactionOutput)
{
return transactionOutput.getScriptPubKey().getChunks().get(0).equalsOpCode(ScriptOpCodes.OP_RETURN);
}
private void notifyBalanceListeners(Transaction tx)
{
for (int i = 0; i < balanceListeners.size(); i++)
{
BalanceListener balanceListener = balanceListeners.get(i);
List<TransactionOutput> transactionOutputs = tx.getOutputs();
for (int n = 0; n < transactionOutputs.size(); n++)
{
TransactionOutput transactionOutput = transactionOutputs.get(n);
if (!isOpReturnScript(transactionOutput))
{
Address address = transactionOutput.getScriptPubKey().getToAddress(params);
if (address.equals(balanceListener.getAddress()))
{
balanceListener.onBalanceChanged(getBalance(address));
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Key management
///////////////////////////////////////////////////////////////////////////////////////////
public boolean isNewWallet()
{
// walletAppKit creates first key
return wallet.getKeys().size() == 1;
}
public Address getRegistrationAddress()
{
ECKey key = wallet.getKeys().get(0);
return key.toAddress(params);
}
public List<Address> getTradingAddresses()
{
List<Address> addresses = new ArrayList<>();
List<ECKey> keys = wallet.getKeys();
for (int i = 0; i < keys.size(); i++)
{
ECKey key = keys.get(i);
addresses.add(key.toAddress(params));
}
return addresses;
}
public Address createNewAddress()
{
ECKey key = new ECKey();
wallet.addKey(key);
return key.toAddress(params);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Address management
///////////////////////////////////////////////////////////////////////////////////////////
public TransactionConfidence getConfidence(Address address)
{
Set<Transaction> transactions = wallet.getTransactions(true);
if (transactions != null)
{
for (Transaction tx : transactions)
{
List<TransactionOutput> transactionOutputs = tx.getOutputs();
for (int n = 0; n < transactionOutputs.size(); n++)
{
TransactionOutput transactionOutput = transactionOutputs.get(n);
if (!isOpReturnScript(transactionOutput))
{
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
if (addressOutput.equals(address))
{
return tx.getConfidence();
}
}
else
{
return null;
}
}
}
}
return null;
}
public BigInteger getBalance(Address address)
{
LinkedList<TransactionOutput> all = wallet.calculateAllSpendCandidates(false);
BigInteger value = BigInteger.ZERO;
for (TransactionOutput transactionOutput : all)
{
if (!isOpReturnScript(transactionOutput))
{
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
if (addressOutput.equals(address))
{
value = value.add(transactionOutput.getValue());
}
}
}
return value;
/* Set<Transaction> transactions = wallet.getTransactions(true);
if (transactions != null)
{
for (Transaction tx : transactions)
{
List<TransactionOutput> transactionOutputs = tx.getOutputs();
for (int n = 0; n < transactionOutputs.size(); n++)
{
TransactionOutput transactionOutput = transactionOutputs.get(n);
if (!isOpReturnScript(transactionOutput))
{
Address addressOutput = transactionOutput.getScriptPubKey().getToAddress(params);
if (addressOutput.equals(address))
{
return tx.getValueSentToMe(wallet);
}
}
else
{
return BigInteger.ZERO;
}
}
}
}
return BigInteger.ZERO; */
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Trading wallet // Trading wallet
@ -146,7 +370,7 @@ public class WalletFacade
public String getTradingAddress() public String getTradingAddress()
{ {
return tradingKey.toAddress(params).toString(); return getTradingKey().toAddress(params).toString();
} }
public Wallet getWallet() public Wallet getWallet()
@ -156,36 +380,58 @@ public class WalletFacade
public String getPubKeyAsHex() public String getPubKeyAsHex()
{ {
return Utils.bytesToHexString(tradingKey.getPubKey()); return Utils.bytesToHexString(getTradingKey().getPubKey());
} }
//TODO
public ECKey getTradingKey()
{
return wallet.getKeys().get(1);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Arbitration key
///////////////////////////////////////////////////////////////////////////////////////////
public String getArbitratorPubKeyAsHex()
{
if (arbitratorKey == null)
{
arbitratorKey = new ECKey();
wallet.addKey(arbitratorKey);
}
return Utils.bytesToHexString(arbitratorKey.getPubKey());
}
//TODO separate wallets
public BigInteger getCollateralBalance()
{
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Account registration // Account registration
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public Address getRegistrationAddress() public BigInteger getRegistrationBalance()
{ {
return registrationKey.toAddress(params); return getBalance(getRegistrationAddress());
} }
public ECKey getRegistrationKey() public ECKey getRegistrationKey()
{ {
return registrationKey; return wallet.getKeys().get(0);
} }
//TODO assume for now that there is only reg address funding, so total wallet balance = reg. balance
public BigInteger getRegistrationBalance()
{
return wallet.getBalance(Wallet.BalanceType.ESTIMATED);
}
public void publishRegistrationTxWithExtraData(String stringifiedBankAccounts) throws InsufficientMoneyException public void publishRegistrationTxWithExtraData(String stringifiedBankAccounts) throws InsufficientMoneyException
{ {
log.debug("publishRegistrationTxWithExtraData"); log.debug("publishRegistrationTxWithExtraData");
log.trace("inputs: "); log.trace("inputs: ");
log.trace("stringifiedBankAccounts " + stringifiedBankAccounts); log.trace("stringifiedBankAccounts " + stringifiedBankAccounts);
byte[] dataToEmbed = cryptoFacade.getEmbeddedAccountRegistrationData(registrationKey, stringifiedBankAccounts); byte[] dataToEmbed = cryptoFacade.getEmbeddedAccountRegistrationData(getRegistrationKey(), stringifiedBankAccounts);
Script script = new ScriptBuilder().op(OP_RETURN).data(dataToEmbed).build(); Script script = new ScriptBuilder().op(OP_RETURN).data(dataToEmbed).build();
Transaction tx = new Transaction(params); Transaction tx = new Transaction(params);
TransactionOutput dataOutput = new TransactionOutput(params, tx, Transaction.MIN_NONDUST_OUTPUT, script.getProgram()); TransactionOutput dataOutput = new TransactionOutput(params, tx, Transaction.MIN_NONDUST_OUTPUT, script.getProgram());
@ -556,7 +802,7 @@ public class WalletFacade
TransactionOutput multiSigOutput = tx.getInput(0).getConnectedOutput(); TransactionOutput multiSigOutput = tx.getInput(0).getConnectedOutput();
Script multiSigScript = multiSigOutput.getScriptPubKey(); Script multiSigScript = multiSigOutput.getScriptPubKey();
Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false); Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature offererSignature = tradingKey.sign(sigHash); ECKey.ECDSASignature offererSignature = getTradingKey().sign(sigHash);
TransactionSignature offererTxSig = new TransactionSignature(offererSignature, Transaction.SigHash.ALL, false); TransactionSignature offererTxSig = new TransactionSignature(offererSignature, Transaction.SigHash.ALL, false);
Script inputScript = ScriptBuilder.createMultiSigInputScript(ImmutableList.of(offererTxSig)); Script inputScript = ScriptBuilder.createMultiSigInputScript(ImmutableList.of(offererTxSig));
@ -594,7 +840,7 @@ public class WalletFacade
Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false); Sha256Hash sigHash = tx.hashForSignature(0, multiSigScript, Transaction.SigHash.ALL, false);
log.trace("sigHash=" + sigHash.toString()); log.trace("sigHash=" + sigHash.toString());
ECKey.ECDSASignature takerSignature = tradingKey.sign(sigHash); ECKey.ECDSASignature takerSignature = getTradingKey().sign(sigHash);
TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false); TransactionSignature takerTxSig = new TransactionSignature(takerSignature, Transaction.SigHash.ALL, false);
ECKey.ECDSASignature offererSignature = new ECKey.ECDSASignature(new BigInteger(offererSignatureR), new BigInteger(offererSignatureS)); ECKey.ECDSASignature offererSignature = new ECKey.ECDSASignature(new BigInteger(offererSignatureR), new BigInteger(offererSignatureS));

View file

@ -11,7 +11,7 @@ import io.bitsquare.gui.components.NetworkSyncPane;
import io.bitsquare.gui.market.MarketController; import io.bitsquare.gui.market.MarketController;
import io.bitsquare.gui.setup.SetupController; import io.bitsquare.gui.setup.SetupController;
import io.bitsquare.gui.util.Icons; import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation; import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.TradeMessage; import io.bitsquare.msg.TradeMessage;
import io.bitsquare.trade.Direction; import io.bitsquare.trade.Direction;
@ -43,6 +43,7 @@ import java.util.ResourceBundle;
public class MainController implements Initializable, NavigationController public class MainController implements Initializable, NavigationController
{ {
private static final Logger log = LoggerFactory.getLogger(MainController.class); private static final Logger log = LoggerFactory.getLogger(MainController.class);
private static MainController mainController;
private User user; private User user;
private WalletFacade walletFacade; private WalletFacade walletFacade;
@ -80,6 +81,13 @@ public class MainController implements Initializable, NavigationController
this.walletFacade = walletFacade; this.walletFacade = walletFacade;
this.messageFacade = messageFacade; this.messageFacade = messageFacade;
this.trading = trading; this.trading = trading;
MainController.mainController = this;
}
public static MainController getInstance()
{
return mainController;
} }
@ -113,7 +121,7 @@ public class MainController implements Initializable, NavigationController
walletFacade.initWallet(); walletFacade.initWallet();
if (user.getAccountID() == null) /*if (user.getAccountID() == null)
{ {
buildSetupView(); buildSetupView();
anchorPane.setVisible(false); anchorPane.setVisible(false);
@ -121,14 +129,17 @@ public class MainController implements Initializable, NavigationController
rootContainer.getChildren().add(setupView); rootContainer.getChildren().add(setupView);
} }
else else
{ { */
buildNavigation(); buildNavigation();
sellButton.fire(); //homeButton.fire();
// ordersButton.fire(); //settingsButton.fire();
// homeButton.fire(); fundsButton.fire();
// msgButton.fire(); // sellButton.fire();
} // ordersButton.fire();
// homeButton.fire();
// msgButton.fire();
// }
AnchorPane.setBottomAnchor(networkSyncPane, 0.0); AnchorPane.setBottomAnchor(networkSyncPane, 0.0);
AnchorPane.setLeftAnchor(networkSyncPane, 0.0); AnchorPane.setLeftAnchor(networkSyncPane, 0.0);
@ -158,10 +169,39 @@ public class MainController implements Initializable, NavigationController
} }
} }
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: NavigationController // Interface implementation: NavigationController
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override
public ChildController navigateToView(String fxmlView)
{
// use the buttons to trigger the change to get the correct button states
switch (fxmlView)
{
case NavigationController.HOME:
homeButton.fire();
break;
case NavigationController.FUNDS:
fundsButton.fire();
break;
case NavigationController.HISTORY:
historyButton.fire();
break;
case NavigationController.MSG:
msgButton.fire();
break;
case NavigationController.ORDERS:
ordersButton.fire();
break;
case NavigationController.SETTINGS:
settingsButton.fire();
break;
}
return navigateToView(fxmlView, "");
}
@Override @Override
public ChildController navigateToView(String fxmlView, String title) public ChildController navigateToView(String fxmlView, String title)
{ {
@ -218,7 +258,7 @@ public class MainController implements Initializable, NavigationController
{ {
toggleGroup = new ToggleGroup(); toggleGroup = new ToggleGroup();
homeButton = addNavButton(leftNavPane, "Overview", Icons.HOME, Icons.HOME, NavigationController.HOME); homeButton = addNavButton(leftNavPane, "Overview", Icons.HOME, Icons.HOME_ACTIVE, NavigationController.HOME);
buyButtonHolder = new Pane(); buyButtonHolder = new Pane();
buyButton = addNavButton(buyButtonHolder, "Buy BTC", Icons.NAV_BUY, Icons.NAV_BUY_ACTIVE, NavigationController.MARKET, Direction.BUY); buyButton = addNavButton(buyButtonHolder, "Buy BTC", Icons.NAV_BUY, Icons.NAV_BUY_ACTIVE, NavigationController.MARKET, Direction.BUY);
@ -229,20 +269,20 @@ public class MainController implements Initializable, NavigationController
leftNavPane.getChildren().add(sellButtonHolder); leftNavPane.getChildren().add(sellButtonHolder);
ordersButtonButtonHolder = new Pane(); ordersButtonButtonHolder = new Pane();
ordersButton = addNavButton(ordersButtonButtonHolder, "Orders", Icons.ORDERS, Icons.ORDERS, NavigationController.ORDERS); ordersButton = addNavButton(ordersButtonButtonHolder, "Orders", Icons.ORDERS, Icons.ORDERS_ACTIVE, NavigationController.ORDERS);
leftNavPane.getChildren().add(ordersButtonButtonHolder); leftNavPane.getChildren().add(ordersButtonButtonHolder);
historyButton = addNavButton(leftNavPane, "History", Icons.HISTORY, Icons.HISTORY, NavigationController.HISTORY); historyButton = addNavButton(leftNavPane, "History", Icons.HISTORY, Icons.HISTORY_ACTIVE, NavigationController.HISTORY);
fundsButton = addNavButton(leftNavPane, "Funds", Icons.FUNDS, Icons.FUNDS, NavigationController.FUNDS); fundsButton = addNavButton(leftNavPane, "Funds", Icons.FUNDS, Icons.FUNDS_ACTIVE, NavigationController.FUNDS);
msgButtonHolder = new Pane(); msgButtonHolder = new Pane();
msgButton = addNavButton(msgButtonHolder, "Message", Icons.MSG, Icons.MSG, NavigationController.MSG); msgButton = addNavButton(msgButtonHolder, "Message", Icons.MSG, Icons.MSG_ACTIVE, NavigationController.MSG);
leftNavPane.getChildren().add(msgButtonHolder); leftNavPane.getChildren().add(msgButtonHolder);
addBalanceInfo(rightNavPane); addBalanceInfo(rightNavPane);
addAccountComboBox(rightNavPane); addAccountComboBox(rightNavPane);
settingsButton = addNavButton(rightNavPane, "Settings", Icons.SETTINGS, Icons.SETTINGS, NavigationController.SETTINGS); settingsButton = addNavButton(rightNavPane, "Settings", Icons.SETTINGS, Icons.SETTINGS_ACTIVE, NavigationController.SETTINGS);
} }
private ToggleButton addNavButton(Pane parent, String title, String iconId, String iconIdActivated, String navTarget) private ToggleButton addNavButton(Pane parent, String title, String iconId, String iconIdActivated, String navTarget)

View file

@ -17,5 +17,12 @@ public interface NavigationController
public static final String OFFERER_TRADE = "/io/bitsquare/gui/orders/OffererTradeView.fxml"; public static final String OFFERER_TRADE = "/io/bitsquare/gui/orders/OffererTradeView.fxml";
public static final String CREATE_OFFER = "/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml"; public static final String CREATE_OFFER = "/io/bitsquare/gui/market/createOffer/CreateOfferView.fxml";
public static final String ARBITRATOR_PROFILE = "/io/bitsquare/gui/arbitrators/profile/ArbitratorProfileView.fxml";
public static final String ARBITRATOR_OVERVIEW = "/io/bitsquare/gui/arbitrators/overview/ArbitratorOverviewView.fxml";
public static final String ARBITRATOR_REGISTRATION = "/io/bitsquare/gui/arbitrators/registration/ArbitratorRegistrationView.fxml";
ChildController navigateToView(String fxmlView);
ChildController navigateToView(String fxmlView, String title); ChildController navigateToView(String fxmlView, String title);
} }

View file

@ -0,0 +1,235 @@
package io.bitsquare.gui.arbitrators.overview;
import com.google.inject.Inject;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.arbitrators.profile.ArbitratorProfileController;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.listeners.ArbitratorListener;
import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage;
import io.bitsquare.user.Arbitrator;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import net.tomp2p.peers.Number160;
import net.tomp2p.storage.Data;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
public class ArbitratorOverviewController implements Initializable, ChildController, NavigationController, ArbitratorListener
{
private Settings settings;
private Storage storage;
private MessageFacade messageFacade;
private Arbitrator currentArbitrator;
private NavigationController navigationController;
private ArbitratorProfileController arbitratorProfileController;
private List<Arbitrator> allArbitrators = new ArrayList<>();
private int index = -1;
@FXML
private Button prevButton, nextButton, selectButton;
@FXML
private AnchorPane rootContainer;
@FXML
private Pane arbitratorProfile;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ArbitratorOverviewController(Settings settings, Storage storage, MessageFacade messageFacade)
{
this.settings = settings;
this.storage = storage;
this.messageFacade = messageFacade;
messageFacade.addArbitratorListener(this);
messageFacade.getArbitrators(LanguageUtil.getDefaultLanguageLocale());
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb)
{
navigateToView(NavigationController.ARBITRATOR_PROFILE, "");
checkButtonState();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setNavigationController(NavigationController navigationController)
{
this.navigationController = navigationController;
}
@Override
public void cleanup()
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: NavigationController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public ChildController navigateToView(String fxmlView)
{
return navigateToView(fxmlView, "");
}
@Override
public ChildController navigateToView(String fxmlView, String title)
{
if (arbitratorProfileController != null)
arbitratorProfileController.cleanup();
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
try
{
final Node view = loader.load();
arbitratorProfileController = loader.getController();
arbitratorProfileController.setNavigationController(this);
rootContainer.getChildren().set(0, view);
return arbitratorProfileController;
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ArbitratorListener
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void onArbitratorAdded(Data offerData, boolean success)
{
}
@Override
public void onArbitratorsReceived(Map<Number160, Data> dataMap, boolean success)
{
if (success && dataMap != null)
{
allArbitrators.clear();
for (Data arbitratorData : dataMap.values())
{
try
{
Object arbitratorDataObject = arbitratorData.getObject();
if (arbitratorDataObject instanceof Arbitrator && arbitratorDataObject != null)
{
Arbitrator arbitrator = (Arbitrator) arbitratorDataObject;
allArbitrators.add(arbitrator);
}
} catch (ClassNotFoundException | IOException e)
{
e.printStackTrace();
}
}
}
else
{
allArbitrators.clear();
}
if (allArbitrators.size() > 0)
{
index = 0;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileController.applyArbitrator(currentArbitrator);
checkButtonState();
}
}
@Override
public void onArbitratorRemoved(Data data, boolean success)
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onPrevious(ActionEvent actionEvent)
{
if (index > 0)
{
index--;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileController.applyArbitrator(currentArbitrator);
}
checkButtonState();
}
@FXML
public void onNext(ActionEvent actionEvent)
{
if (index < allArbitrators.size() - 1)
{
index++;
currentArbitrator = allArbitrators.get(index);
arbitratorProfileController.applyArbitrator(currentArbitrator);
}
checkButtonState();
}
@FXML
public void onSelect(ActionEvent actionEvent)
{
settings.addAcceptedArbitrator(currentArbitrator);
storage.write(settings.getClass().getName(), settings);
}
@FXML
public void onClose(ActionEvent actionEvent)
{
Stage stage = (Stage) rootContainer.getScene().getWindow();
stage.close();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void checkButtonState()
{
prevButton.setDisable(index < 1);
nextButton.setDisable(index == allArbitrators.size() - 1 || index == -1);
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="rootContainer" prefHeight="600" prefWidth="800" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.bitsquare.gui.arbitrators.overview.ArbitratorOverviewController">
<children>
<Pane fx:id="arbitratorProfile"/>
<Button fx:id="prevButton" text="Previous" onAction="#onPrevious" AnchorPane.bottomAnchor="45.0" AnchorPane.leftAnchor="10.0"/>
<Button fx:id="nextButton" text="Next" onAction="#onNext" AnchorPane.bottomAnchor="45.0" AnchorPane.rightAnchor="10.0"/>
<Button fx:id="selectButton" text="Select" onAction="#onSelect" AnchorPane.bottomAnchor="45.0" AnchorPane.leftAnchor="350.0"/>
<Button fx:id="closeButton" text="close" onAction="#onClose" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0"/>
</children>
</AnchorPane>

View file

@ -0,0 +1,130 @@
package io.bitsquare.gui.arbitrators.profile;
import com.google.inject.Inject;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage;
import io.bitsquare.user.Arbitrator;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import java.net.URL;
import java.util.ResourceBundle;
public class ArbitratorProfileController implements Initializable, ChildController
{
private Settings settings;
private Storage storage;
private Arbitrator arbitrator;
private NavigationController navigationController;
@FXML
private Label nameLabel;
@FXML
private TextField nameTextField, languagesTextField, reputationTextField, maxTradeVolumeTextField, passiveServiceFeeTextField,
arbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField;
@FXML
private TextArea descriptionTextArea;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ArbitratorProfileController(Settings settings, Storage storage)
{
this.settings = settings;
this.storage = storage;
Settings savedSettings = (Settings) storage.read(settings.getClass().getName());
if (savedSettings != null)
{
settings.updateFromStorage(savedSettings);
}
else
{
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void applyArbitrator(Arbitrator arbitrator)
{
if (arbitrator != null)
{
String name = "";
switch (arbitrator.getIdType())
{
case REAL_LIFE_ID:
name = "Name:";
break;
case NICKNAME:
name = "Nickname:";
break;
case COMPANY:
name = "Company:";
break;
}
nameLabel.setText(name);
nameTextField.setText(arbitrator.getName());
languagesTextField.setText(BitSquareFormatter.languageLocalesToString(arbitrator.getLanguages()));
reputationTextField.setText(arbitrator.getReputation().toString());
maxTradeVolumeTextField.setText(String.valueOf(arbitrator.getMaxTradeVolume()) + " BTC");
passiveServiceFeeTextField.setText(String.valueOf(arbitrator.getPassiveServiceFee()) + " % (Min. " + String.valueOf(arbitrator.getMinPassiveServiceFee()) + " BTC)");
arbitrationFeeTextField.setText(String.valueOf(arbitrator.getArbitrationFee()) + " % (Min. " + String.valueOf(arbitrator.getMinArbitrationFee()) + " BTC)");
methodsTextField.setText(BitSquareFormatter.arbitrationMethodsToString(arbitrator.getArbitrationMethods()));
idVerificationsTextField.setText(BitSquareFormatter.arbitrationIDVerificationsToString(arbitrator.getIdVerifications()));
webPageTextField.setText(arbitrator.getWebUrl());
descriptionTextArea.setText(arbitrator.getDescription());
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb)
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setNavigationController(NavigationController navigationController)
{
this.navigationController = navigationController;
}
@Override
public void cleanup()
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
}

View file

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<GridPane hgap="5.0" vgap="5.0" AnchorPane.bottomAnchor="80.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0" xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.bitsquare.gui.arbitrators.profile.ArbitratorProfileController">
<children>
<Label fx:id="nameLabel" text="Name:"/>
<TextField fx:id="nameTextField" editable="false" GridPane.columnIndex="1"/>
<Label text="Languages:" GridPane.rowIndex="1"/>
<TextField fx:id="languagesTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<Label text="Reputation:" GridPane.rowIndex="2"/>
<TextField fx:id="reputationTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Label text="Max. trade volume:" GridPane.rowIndex="3"/>
<TextField fx:id="maxTradeVolumeTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
<Label text="Passive service fee:" GridPane.rowIndex="4"/>
<TextField fx:id="passiveServiceFeeTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<Label text="Arbitration fee:" GridPane.rowIndex="5"/>
<TextField fx:id="arbitrationFeeTextField" editable="false" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="5"/>
<Label text="Methods of arbitration:" GridPane.rowIndex="6"/>
<TextField fx:id="methodsTextField" editable="false" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="6"/>
<Label text="ID verifications:" GridPane.rowIndex="7"/>
<TextField fx:id="idVerificationsTextField" editable="false" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="7"/>
<Label text="Web page:" GridPane.rowIndex="9"/>
<TextField fx:id="webPageTextField" editable="false" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="9"/>
<Label text="Description:" GridPane.rowIndex="10" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
</Label>
<TextArea fx:id="descriptionTextArea" editable="false" prefHeight="150.0" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.rowIndex="10"/>
</children>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0"/>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="ALWAYS"/>
</rowConstraints>
</GridPane>

View file

@ -0,0 +1,526 @@
package io.bitsquare.gui.arbitrators.registration;
import com.google.bitcoin.core.ECKey;
import com.google.bitcoin.core.Transaction;
import com.google.bitcoin.core.Wallet;
import com.google.bitcoin.core.WalletEventListener;
import com.google.bitcoin.script.Script;
import com.google.inject.Inject;
import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.arbitrators.profile.ArbitratorProfileController;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.BitSquareConverter;
import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.gui.util.BitSquareValidator;
import io.bitsquare.gui.util.ConfidenceDisplay;
import io.bitsquare.locale.LanguageUtil;
import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade;
import io.bitsquare.storage.Storage;
import io.bitsquare.user.Arbitrator;
import io.bitsquare.user.Reputation;
import io.bitsquare.util.DSAKeyUtil;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URL;
import java.util.*;
public class ArbitratorRegistrationController implements Initializable, ChildController
{
private static final Logger log = LoggerFactory.getLogger(ArbitratorRegistrationController.class);
private Storage storage;
private WalletFacade walletFacade;
private MessageFacade messageFacade;
private Arbitrator arbitrator;
private ArbitratorProfileController arbitratorProfileController;
private boolean isEditMode;
private List<Locale> languageList = new ArrayList<>();
private List<Arbitrator.METHODS> methodList = new ArrayList<>();
private List<Arbitrator.ID_VERIFICATIONS> idVerificationList = new ArrayList<>();
private Arbitrator.ID_TYPE idType;
private ConfidenceDisplay confidenceDisplay;
@FXML
private AnchorPane rootContainer;
@FXML
private Accordion accordion;
@FXML
private TitledPane profileTitledPane, payCollateralTitledPane;
@FXML
private Button saveProfileButton, paymentDoneButton;
@FXML
private Label nameLabel, infoLabel, copyIcon, confirmationLabel;
@FXML
private ComboBox<Locale> languageComboBox;
@FXML
private ComboBox<Arbitrator.ID_TYPE> idTypeComboBox;
@FXML
private ComboBox<Arbitrator.METHODS> methodsComboBox;
@FXML
private ComboBox<Arbitrator.ID_VERIFICATIONS> idVerificationsComboBox;
@FXML
private TextField nameTextField, idTypeTextField, languagesTextField, maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField,
arbitrationFeeTextField, minArbitrationFeeTextField, methodsTextField, idVerificationsTextField, webPageTextField, collateralAddressTextField, balanceTextField;
@FXML
private TextArea descriptionTextArea;
@FXML
private ConfidenceProgressIndicator progressIndicator;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public ArbitratorRegistrationController(Storage storage, WalletFacade walletFacade, MessageFacade messageFacade)
{
this.storage = storage;
this.walletFacade = walletFacade;
this.messageFacade = messageFacade;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void setEditMode(boolean isEditMode)
{
this.isEditMode = isEditMode;
if (isEditMode)
{
saveProfileButton.setText("Save");
profileTitledPane.setCollapsible(false);
payCollateralTitledPane.setVisible(false);
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void initialize(URL url, ResourceBundle rb)
{
accordion.setExpandedPane(profileTitledPane);
arbitrator = new Arbitrator();
Arbitrator savedArbitrator = (Arbitrator) storage.read(arbitrator.getClass().getName());
if (savedArbitrator != null)
{
arbitrator.updateFromStorage(savedArbitrator);
applyArbitrator();
}
else
{
languageList.add(LanguageUtil.getDefaultLanguageLocale());
languagesTextField.setText(BitSquareFormatter.languageLocalesToString(languageList));
}
languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales()));
languageComboBox.setConverter(new StringConverter<Locale>()
{
@Override
public String toString(Locale locale)
{
return locale.getDisplayLanguage();
}
@Override
public Locale fromString(String s)
{
return null;
}
});
idTypeComboBox.setItems(FXCollections.observableArrayList(new ArrayList<>(EnumSet.allOf(Arbitrator.ID_TYPE.class))));
idTypeComboBox.setConverter(new StringConverter<Arbitrator.ID_TYPE>()
{
@Override
public String toString(Arbitrator.ID_TYPE item)
{
return Localisation.get(item.toString());
}
@Override
public Arbitrator.ID_TYPE fromString(String s)
{
return null;
}
});
methodsComboBox.setItems(FXCollections.observableArrayList(new ArrayList<>(EnumSet.allOf(Arbitrator.METHODS.class))));
methodsComboBox.setConverter(new StringConverter<Arbitrator.METHODS>()
{
@Override
public String toString(Arbitrator.METHODS item)
{
return Localisation.get(item.toString());
}
@Override
public Arbitrator.METHODS fromString(String s)
{
return null;
}
});
idVerificationsComboBox.setItems(FXCollections.observableArrayList(new ArrayList<>(EnumSet.allOf(Arbitrator.ID_VERIFICATIONS.class))));
idVerificationsComboBox.setConverter(new StringConverter<Arbitrator.ID_VERIFICATIONS>()
{
@Override
public String toString(Arbitrator.ID_VERIFICATIONS item)
{
return Localisation.get(item.toString());
}
@Override
public Arbitrator.ID_VERIFICATIONS fromString(String s)
{
return null;
}
});
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public void setNavigationController(NavigationController navigationController)
{
}
@Override
public void cleanup()
{
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onSelectIDType(ActionEvent actionEvent)
{
idType = idTypeComboBox.getSelectionModel().getSelectedItem();
if (idType != null)
{
idTypeTextField.setText(Localisation.get(idType.toString()));
String name = "";
switch (idType)
{
case REAL_LIFE_ID:
name = "Name:";
break;
case NICKNAME:
name = "Nickname:";
break;
case COMPANY:
name = "Company:";
break;
}
nameLabel.setText(name);
idTypeComboBox.getSelectionModel().clearSelection();
}
}
@FXML
public void onAddLanguage(ActionEvent actionEvent)
{
Locale item = languageComboBox.getSelectionModel().getSelectedItem();
if (!languageList.contains(item) && item != null)
{
languageList.add(item);
languagesTextField.setText(BitSquareFormatter.languageLocalesToString(languageList));
languageComboBox.getSelectionModel().clearSelection();
}
}
@FXML
public void onClearLanguages(ActionEvent actionEvent)
{
languageList.clear();
languagesTextField.setText("");
}
@FXML
public void onAddMethod(ActionEvent actionEvent)
{
Arbitrator.METHODS item = methodsComboBox.getSelectionModel().getSelectedItem();
if (!methodList.contains(item) && item != null)
{
methodList.add(item);
methodsTextField.setText(BitSquareFormatter.arbitrationMethodsToString(methodList));
methodsComboBox.getSelectionModel().clearSelection();
}
}
@FXML
public void onClearMethods(ActionEvent actionEvent)
{
methodList.clear();
methodsTextField.setText("");
}
@FXML
public void onAddIDVerification(ActionEvent actionEvent)
{
Arbitrator.ID_VERIFICATIONS item = idVerificationsComboBox.getSelectionModel().getSelectedItem();
if (item != null)
{
if (!idVerificationList.contains(item))
{
idVerificationList.add(item);
idVerificationsTextField.setText(BitSquareFormatter.arbitrationIDVerificationsToString(idVerificationList));
}
}
idVerificationsComboBox.getSelectionModel().clearSelection();
}
@FXML
public void onClearIDVerifications(ActionEvent actionEvent)
{
idVerificationList.clear();
idVerificationsTextField.setText("");
}
@FXML
public void onSaveProfile(ActionEvent actionEvent)
{
arbitrator = getEditedArbitrator();
if (arbitrator != null)
{
storage.write(arbitrator.getClass().getName(), arbitrator);
if (isEditMode)
{
close();
}
else
{
setupPayCollateralScreen();
accordion.setExpandedPane(payCollateralTitledPane);
}
}
try
{
messageFacade.addArbitrator(arbitrator);
} catch (IOException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
}
@FXML
public void onPaymentDone(ActionEvent actionEvent)
{
//To change body of created methods use File | Settings | File Templates.
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void setupPayCollateralScreen()
{
infoLabel.setText("You need to pay 10 x the max. trading volume as collateral.\n\n" +
"That payment will be locked into a MultiSig fund and be refunded when you leave the arbitration pool.\n" +
"In case of fraud (collusion, not fulfilling the min. dispute quality requirements) you will lose your collateral.\n" +
"If you have a negative feedback from your clients you will lose a part of the collateral,\n" +
"depending on the overall relation of negative to positive ratings you received after a dispute resolution.\n\n" +
"Please pay in " + arbitrator.getMaxTradeVolume() * 10 + " BTC");
String collateralAddress = walletFacade.getRegistrationAddress().toString();
collateralAddressTextField.setText(collateralAddress);
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
copyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(collateralAddress);
clipboard.setContent(content);
});
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, balanceTextField, progressIndicator);
paymentDoneButton.setDisable(walletFacade.getCollateralBalance().compareTo(BigInteger.ZERO) == 0);
log.debug("getCollateralBalance " + walletFacade.getCollateralBalance().toString());
walletFacade.getWallet().addEventListener(new WalletEventListener()
{
@Override
public void onCoinsReceived(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
paymentDoneButton.setDisable(newBalance.compareTo(BigInteger.ZERO) == 0);
}
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx)
{
}
@Override
public void onCoinsSent(Wallet wallet, Transaction tx, BigInteger prevBalance, BigInteger newBalance)
{
}
@Override
public void onReorganize(Wallet wallet)
{
}
@Override
public void onWalletChanged(Wallet wallet)
{
}
@Override
public void onKeysAdded(Wallet wallet, List<ECKey> keys)
{
}
@Override
public void onScriptsAdded(Wallet wallet, List<Script> scripts)
{
}
});
}
private void applyArbitrator()
{
if (arbitrator != null)
{
String name = "";
switch (arbitrator.getIdType())
{
case REAL_LIFE_ID:
name = "Name:";
break;
case NICKNAME:
name = "Nickname:";
break;
case COMPANY:
name = "Company:";
break;
}
nameLabel.setText(name);
nameTextField.setText(arbitrator.getName());
idTypeTextField.setText(Localisation.get(arbitrator.getIdType().toString()));
languagesTextField.setText(BitSquareFormatter.languageLocalesToString(arbitrator.getLanguages()));
maxTradeVolumeTextField.setText(String.valueOf(arbitrator.getMaxTradeVolume()));
passiveServiceFeeTextField.setText(String.valueOf(arbitrator.getPassiveServiceFee()));
minPassiveServiceFeeTextField.setText(String.valueOf(arbitrator.getMinPassiveServiceFee()));
arbitrationFeeTextField.setText(String.valueOf(arbitrator.getArbitrationFee()));
minArbitrationFeeTextField.setText(String.valueOf(arbitrator.getMinArbitrationFee()));
methodsTextField.setText(BitSquareFormatter.arbitrationMethodsToString(arbitrator.getArbitrationMethods()));
idVerificationsTextField.setText(BitSquareFormatter.arbitrationIDVerificationsToString(arbitrator.getIdVerifications()));
webPageTextField.setText(arbitrator.getWebUrl());
descriptionTextArea.setText(arbitrator.getDescription());
idType = arbitrator.getIdType();
languageList = arbitrator.getLanguages();
methodList = arbitrator.getArbitrationMethods();
idVerificationList = arbitrator.getIdVerifications();
}
}
private Arbitrator getEditedArbitrator()
{
try
{
TextField[] notEmptyTextFields = {nameTextField, idTypeTextField, languagesTextField, methodsTextField, idVerificationsTextField};
BitSquareValidator.resetTextFields(notEmptyTextFields);
BitSquareValidator.textFieldsNotEmpty(notEmptyTextFields);
TextField[] hasDoubleValueTextFields = {maxTradeVolumeTextField, passiveServiceFeeTextField, minPassiveServiceFeeTextField, arbitrationFeeTextField, minArbitrationFeeTextField};
BitSquareValidator.resetTextFields(hasDoubleValueTextFields);
BitSquareValidator.textFieldsHasDoubleValue(hasDoubleValueTextFields);
String pubKeyAsHex = walletFacade.getArbitratorPubKeyAsHex();
String messagePubKeyAsHex = DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey());
String name = nameTextField.getText();
double maxTradeVolume = BitSquareConverter.stringToDouble(maxTradeVolumeTextField.getText());
double passiveServiceFee = BitSquareConverter.stringToDouble(passiveServiceFeeTextField.getText());
double minPassiveServiceFee = BitSquareConverter.stringToDouble(minPassiveServiceFeeTextField.getText());
double arbitrationFee = BitSquareConverter.stringToDouble(arbitrationFeeTextField.getText());
double minArbitrationFee = BitSquareConverter.stringToDouble(minArbitrationFeeTextField.getText());
String webUrl = webPageTextField.getText();
String description = descriptionTextArea.getText();
return new Arbitrator(pubKeyAsHex,
messagePubKeyAsHex,
name,
idType,
languageList,
new Reputation(),
maxTradeVolume,
passiveServiceFee,
minPassiveServiceFee,
arbitrationFee,
minArbitrationFee,
methodList,
idVerificationList,
webUrl,
description);
} catch (BitSquareValidator.ValidationException e)
{
return null;
}
}
private boolean isInputValid()
{
String[] stringInputs = {nameTextField.getText(),
descriptionTextArea.getText()
};
boolean result = BitSquareValidator.validateStringsNotEmpty(stringInputs);
String[] doubleInputs = {maxTradeVolumeTextField.getText(),
passiveServiceFeeTextField.getText(),
minPassiveServiceFeeTextField.getText(),
arbitrationFeeTextField.getText(),
minArbitrationFeeTextField.getText()
};
result &= BitSquareValidator.validateStringsAsDouble(doubleInputs);
return result;
}
private void close()
{
Stage stage = (Stage) rootContainer.getScene().getWindow();
stage.close();
}
}

View file

@ -0,0 +1,161 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:id="rootContainer" prefHeight="600" prefWidth="800" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.bitsquare.gui.arbitrators.registration.ArbitratorRegistrationController">
<children>
<Accordion fx:id="accordion" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
<panes>
<TitledPane fx:id="profileTitledPane" text="Profile" expanded="true">
<content>
<GridPane hgap="5.0" vgap="5.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0">
<children>
<Label fx:id="nameLabel" text="Name:"/>
<TextField fx:id="nameTextField" GridPane.columnIndex="1" GridPane.columnSpan="3"/>
<Label text="ID type:" GridPane.rowIndex="1"/>
<TextField fx:id="idTypeTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<ComboBox fx:id="idTypeComboBox" onAction="#onSelectIDType" promptText="Select ID type" prefWidth="150.0" GridPane.columnIndex="3" GridPane.rowIndex="1"/>
<Label text="Supported language(s):" GridPane.rowIndex="2"/>
<TextField fx:id="languagesTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Button onAction="#onClearLanguages" text="Clear" GridPane.columnIndex="2" GridPane.rowIndex="2"/>
<ComboBox fx:id="languageComboBox" onAction="#onAddLanguage" prefWidth="150.0" promptText="Add language" GridPane.columnIndex="3" GridPane.rowIndex="2"/>
<Label text="Max. trade volume (BTC):" GridPane.rowIndex="3"/>
<TextField fx:id="maxTradeVolumeTextField" promptText="Recommended: 0.1 - 2 BTC" GridPane.columnIndex="1" GridPane.rowIndex="3" GridPane.columnSpan="3"/>
<Label text="Passive service fee (%):" GridPane.rowIndex="4"/>
<TextField fx:id="passiveServiceFeeTextField" promptText="Recommended: 0.1 - 1%" GridPane.columnIndex="1" GridPane.rowIndex="4" GridPane.columnSpan="3"/>
<Label text="Min. passive service fee (BTC)" GridPane.rowIndex="5"/>
<TextField fx:id="minPassiveServiceFeeTextField" promptText="Recommended: 0.0001 - 0.005 BTC" GridPane.columnIndex="1" GridPane.rowIndex="5" GridPane.columnSpan="3"/>
<Label text="Arbitration fee (%):" GridPane.rowIndex="6"/>
<TextField fx:id="arbitrationFeeTextField" promptText="Recommended: 5 - 20 %" GridPane.columnIndex="1" GridPane.rowIndex="6" GridPane.columnSpan="3"/>
<Label text="Min. arbitration fee (BTC):" GridPane.rowIndex="7"/>
<TextField fx:id="minArbitrationFeeTextField" promptText="Recommended: 0.1 - 0.2 BTC" GridPane.columnIndex="1" GridPane.rowIndex="7" GridPane.columnSpan="3"/>
<Label text="Method(s) used for arbitration:" GridPane.rowIndex="8"/>
<TextField fx:id="methodsTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="8"/>
<Button onAction="#onClearMethods" text="Clear" GridPane.columnIndex="2" GridPane.rowIndex="8"/>
<ComboBox fx:id="methodsComboBox" onAction="#onAddMethod" prefWidth="150.0" promptText="Add method" GridPane.columnIndex="3" GridPane.rowIndex="8"/>
<Label text="Offer ID verification(s):" GridPane.rowIndex="9"/>
<TextField fx:id="idVerificationsTextField" promptText="Optional" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="9"/>
<Button onAction="#onClearIDVerifications" text="Clear" GridPane.columnIndex="2" GridPane.rowIndex="9"/>
<ComboBox fx:id="idVerificationsComboBox" onAction="#onAddIDVerification" prefWidth="150.0" promptText="Add verification" GridPane.columnIndex="3"
GridPane.rowIndex="9"/>
<Label text="Web page:" GridPane.rowIndex="10"/>
<TextField fx:id="webPageTextField" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="10"/>
<Label text="Description:" GridPane.rowIndex="11" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="10.0"/>
</GridPane.margin>
</Label>
<TextArea fx:id="descriptionTextArea" prefHeight="150.0" GridPane.columnIndex="1" GridPane.columnSpan="3" GridPane.rowIndex="11"/>
<Button fx:id="saveProfileButton" defaultButton="true" onAction="#onSaveProfile" text="Next" GridPane.columnIndex="1" GridPane.rowIndex="12"/>
</children>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="10.0"/>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0"/>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="150.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="30.0" prefHeight="30.0" vgrow="SOMETIMES"/>
</rowConstraints>
</GridPane>
</content>
</TitledPane>
<TitledPane fx:id="payCollateralTitledPane" text="Pay collateral">
<content>
<AnchorPane>
<children>
<VBox spacing="20" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label fx:id="infoLabel"/>
<GridPane hgap="5.0" vgap="5.0">
<children>
<Label text="Collateral address:"/>
<TextField fx:id="collateralAddressTextField" editable="false" GridPane.columnIndex="1"/>
<Label fx:id="copyIcon" id="copy-icon" GridPane.columnIndex="2">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
<tooltip>
<Tooltip text="Copy address to clipboard"/>
</tooltip>
</Label>
<Label text="Balance:" GridPane.rowIndex="1"/>
<TextField fx:id="balanceTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<ConfidenceProgressIndicator fx:id="progressIndicator" GridPane.columnIndex="2" GridPane.halignment="LEFT"
GridPane.rowIndex="1" GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="2.0"/>
</GridPane.margin>
</ConfidenceProgressIndicator>
<Label fx:id="confirmationLabel" text="Checking confirmations..." GridPane.columnIndex="3" GridPane.rowIndex="1"/>
<Button fx:id="paymentDoneButton" defaultButton="true" onAction="#onPaymentDone" text="Payment done" disable="true" GridPane.columnIndex="1"
GridPane.rowIndex="2"/>
</children>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="ALWAYS"/>
<ColumnConstraints hgrow="SOMETIMES" prefWidth="20.0" minWidth="20"/>
<ColumnConstraints hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="SOMETIMES"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES"/>
</rowConstraints>
</GridPane>
</children>
</VBox>
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</children>
</AnchorPane>

View file

@ -0,0 +1,272 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package io.bitsquare.gui.components.confidence;
import io.bitsquare.gui.components.confidence.skin.ConfidenceProgressIndicatorSkin;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.DoublePropertyBase;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.css.PseudoClass;
import javafx.css.StyleableProperty;
import javafx.scene.control.Control;
import javafx.scene.control.Skin;
/**
* A circular control which is used for indicating progress, either
* infinite (aka indeterminate) or finite. Often used with the Task API for
* representing progress of background Tasks.
* <p>
* ProgressIndicator sets focusTraversable to false.
* </p>
* <p/>
* <p/>
* This first example creates a ProgressIndicator with an indeterminate value :
* <pre><code>
* import javafx.scene.control.ProgressIndicator;
* ProgressIndicator p1 = new ProgressIndicator();
* </code></pre>
* <p/>
* <p/>
* This next example creates a ProgressIndicator which is 25% complete :
* <pre><code>
* import javafx.scene.control.ProgressIndicator;
* ProgressIndicator p2 = new ProgressIndicator();
* p2.setProgress(0.25F);
* </code></pre>
* <p/>
* Implementation of ProgressIndicator According to JavaFX UI Control API Specification
*
* @since JavaFX 2.0
*/
public class ConfidenceProgressIndicator extends Control
{
/**
* Value for progress indicating that the progress is indeterminate.
*
* @see #setProgress
*/
public static final double INDETERMINATE_PROGRESS = -1;
/***************************************************************************
* *
* Constructors *
* *
**************************************************************************/
/**
* Creates a new indeterminate ProgressIndicator.
*/
public ConfidenceProgressIndicator()
{
this(INDETERMINATE_PROGRESS);
}
/**
* Creates a new ProgressIndicator with the given progress value.
*/
public ConfidenceProgressIndicator(double progress)
{
// focusTraversable is styleable through css. Calling setFocusTraversable
// makes it look to css like the user set the value and css will not
// override. Initializing focusTraversable by calling applyStyle with null
// StyleOrigin ensures that css will be able to override the value.
((StyleableProperty) focusTraversableProperty()).applyStyle(null, Boolean.FALSE);
setProgress(progress);
getStyleClass().setAll(DEFAULT_STYLE_CLASS);
// need to initialize pseudo-class state
final int c = Double.compare(INDETERMINATE_PROGRESS, progress);
pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, c == 0);
pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE, c != 0);
}
/***************************************************************************
* *
* Properties *
* *
**************************************************************************/
/**
* A flag indicating whether it is possible to determine the progress
* of the ProgressIndicator. Typically indeterminate progress bars are
* rendered with some form of animation indicating potentially "infinite"
* progress.
*/
private ReadOnlyBooleanWrapper indeterminate;
private void setIndeterminate(boolean value)
{
indeterminatePropertyImpl().set(value);
}
public final boolean isIndeterminate()
{
return indeterminate == null ? true : indeterminate.get();
}
public final ReadOnlyBooleanProperty indeterminateProperty()
{
return indeterminatePropertyImpl().getReadOnlyProperty();
}
private ReadOnlyBooleanWrapper indeterminatePropertyImpl()
{
if (indeterminate == null)
{
indeterminate = new ReadOnlyBooleanWrapper(true)
{
@Override
protected void invalidated()
{
final boolean active = get();
pseudoClassStateChanged(PSEUDO_CLASS_INDETERMINATE, active);
pseudoClassStateChanged(PSEUDO_CLASS_DETERMINATE, !active);
}
@Override
public Object getBean()
{
return ConfidenceProgressIndicator.this;
}
@Override
public String getName()
{
return "indeterminate";
}
};
}
return indeterminate;
}
/**
* The actual progress of the ProgressIndicator. A negative value for
* progress indicates that the progress is indeterminate. A positive value
* between 0 and 1 indicates the percentage of progress where 0 is 0% and 1
* is 100%. Any value greater than 1 is interpreted as 100%.
*/
private DoubleProperty progress;
public final void setProgress(double value)
{
progressProperty().set(value);
}
public final double getProgress()
{
return progress == null ? INDETERMINATE_PROGRESS : progress.get();
}
public final DoubleProperty progressProperty()
{
if (progress == null)
{
progress = new DoublePropertyBase(-1.0)
{
@Override
protected void invalidated()
{
setIndeterminate(getProgress() < 0.0);
}
@Override
public Object getBean()
{
return ConfidenceProgressIndicator.this;
}
@Override
public String getName()
{
return "progress";
}
};
}
return progress;
}
/***************************************************************************
* *
* Methods *
* *
**************************************************************************/
/**
* {@inheritDoc}
*/
@Override
protected Skin<?> createDefaultSkin()
{
return new ConfidenceProgressIndicatorSkin(this);
}
/***************************************************************************
* *
* Stylesheet Handling *
* *
**************************************************************************/
/**
* Initialize the style class to 'progress-indicator'.
* <p/>
* This is the selector class from which CSS can be used to style
* this control.
*/
private static final String DEFAULT_STYLE_CLASS = "progress-indicator";
/**
* Pseudoclass indicating this is a determinate (i.e., progress can be
* determined) progress indicator.
*/
private static final PseudoClass PSEUDO_CLASS_DETERMINATE =
PseudoClass.getPseudoClass("determinate");
/**
* Pseudoclass indicating this is an indeterminate (i.e., progress cannot
* be determined) progress indicator.
*/
private static final PseudoClass PSEUDO_CLASS_INDETERMINATE =
PseudoClass.getPseudoClass("indeterminate");
/**
* Most Controls return true for focusTraversable, so Control overrides
* this method to return true, but ProgressIndicator returns false for
* focusTraversable's initial value; hence the override of the override.
* This method is called from CSS code to get the correct initial value.
*
* @treatAsPrivate implementation detail
*/
@Deprecated
@Override
protected /*do not make final*/ Boolean impl_cssGetFocusTraversableInitialValue()
{
return Boolean.FALSE;
}
}

View file

@ -0,0 +1,47 @@
package io.bitsquare.gui.components.confidence.behavior;
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import com.sun.javafx.scene.control.behavior.BehaviorBase;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import java.util.Collections;
public class ConfidenceProgressIndicatorBehavior<C extends ConfidenceProgressIndicator> extends BehaviorBase<C>
{
/**
* ************************************************************************
* *
* Constructors *
* *
* ************************************************************************
*/
public ConfidenceProgressIndicatorBehavior(final C progress)
{
super(progress, Collections.emptyList());
}
}

View file

@ -0,0 +1,947 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package io.bitsquare.gui.components.confidence.skin;
import com.sun.javafx.css.converters.BooleanConverter;
import com.sun.javafx.css.converters.PaintConverter;
import com.sun.javafx.css.converters.SizeConverter;
import com.sun.javafx.scene.control.skin.BehaviorSkinBase;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.components.confidence.behavior.ConfidenceProgressIndicatorBehavior;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.css.*;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.NodeOrientation;
import javafx.scene.Node;
import javafx.scene.control.SkinBase;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Region;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.scene.shape.Circle;
import javafx.scene.transform.Scale;
import javafx.util.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ConfidenceProgressIndicatorSkin extends BehaviorSkinBase<ConfidenceProgressIndicator, ConfidenceProgressIndicatorBehavior<ConfidenceProgressIndicator>>
{
/**
* ************************************************************************
* *
* UI Subcomponents *
* *
* ************************************************************************
*/
//private static final String DONE = ControlResources.getString("ProgressIndicator.doneString");
/**
* doneText is just used to know the size of done as that is the biggest text we need to allow for
*/
/* private static final Text doneText = new Text(DONE);
static {
doneText.getStyleClass().add("text");
} */
private IndeterminateSpinner spinner;
private DeterminateIndicator determinateIndicator;
private boolean timelineNulled = false;
/**
* ************************************************************************
* *
* Constructors *
* *
* ************************************************************************
*/
public ConfidenceProgressIndicatorSkin(ConfidenceProgressIndicator control)
{
super(control, new ConfidenceProgressIndicatorBehavior<ConfidenceProgressIndicator>(control));
InvalidationListener indeterminateListener = new InvalidationListener()
{
@Override
public void invalidated(Observable valueModel)
{
initialize();
}
};
control.indeterminateProperty().addListener(indeterminateListener);
InvalidationListener visibilityListener = new InvalidationListener()
{
@Override
public void invalidated(Observable valueModel)
{
if (getSkinnable().isIndeterminate() && timelineNulled && spinner == null)
{
timelineNulled = false;
spinner = new IndeterminateSpinner(getSkinnable(), ConfidenceProgressIndicatorSkin.this, spinEnabled.get(), progressColor.get());
getChildren().add(spinner);
}
if (spinner != null)
{
if (getSkinnable().impl_isTreeVisible() && getSkinnable().getScene() != null)
{
spinner.indeterminateTimeline.play();
}
else
{
spinner.indeterminateTimeline.pause();
getChildren().remove(spinner);
spinner = null;
timelineNulled = true;
}
}
}
};
control.visibleProperty().addListener(visibilityListener);
control.parentProperty().addListener(visibilityListener);
InvalidationListener sceneListener = new InvalidationListener()
{
@Override
public void invalidated(Observable valueModel)
{
if (spinner != null)
{
if (getSkinnable().getScene() == null)
{
spinner.indeterminateTimeline.pause();
getChildren().remove(spinner);
spinner = null;
timelineNulled = true;
}
}
else
{
if (getSkinnable().getScene() != null && getSkinnable().isIndeterminate())
{
timelineNulled = false;
spinner = new IndeterminateSpinner(getSkinnable(), ConfidenceProgressIndicatorSkin.this, spinEnabled.get(), progressColor.get());
getChildren().add(spinner);
if (getSkinnable().impl_isTreeVisible())
{
spinner.indeterminateTimeline.play();
}
getSkinnable().requestLayout();
}
}
}
};
control.sceneProperty().addListener(sceneListener);
initialize();
getSkinnable().requestLayout();
}
private void initialize()
{
ConfidenceProgressIndicator control = getSkinnable();
boolean isIndeterminate = control.isIndeterminate();
if (isIndeterminate)
{
// clean up determinateIndicator
determinateIndicator = null;
// create spinner
spinner = new IndeterminateSpinner(control, this, spinEnabled.get(), progressColor.get());
getChildren().clear();
getChildren().add(spinner);
if (getSkinnable().impl_isTreeVisible())
{
spinner.indeterminateTimeline.play();
}
}
else
{
// clean up after spinner
if (spinner != null)
{
spinner.indeterminateTimeline.stop();
spinner = null;
}
// create determinateIndicator
determinateIndicator = new ConfidenceProgressIndicatorSkin.DeterminateIndicator(control, this, progressColor.get());
getChildren().clear();
getChildren().add(determinateIndicator);
}
}
@Override
public void dispose()
{
super.dispose();
if (spinner != null)
{
spinner.indeterminateTimeline.stop();
spinner = null;
}
}
@Override
protected void layoutChildren(final double x, final double y,
final double w, final double h)
{
if (spinner != null && getSkinnable().isIndeterminate())
{
spinner.layoutChildren();
spinner.resizeRelocate(0, 0, w, h);
}
else if (determinateIndicator != null)
{
determinateIndicator.layoutChildren();
determinateIndicator.resizeRelocate(0, 0, w, h);
}
}
/**
* ************************************************************************
* *
* DeterminateIndicator *
* *
* ************************************************************************
*/
static class DeterminateIndicator extends Region
{
//private double textGap = 2.0F;
// only update progress text on whole percentages
private int intProgress;
// only update pie arc to nearest degree
private int degProgress;
private ConfidenceProgressIndicator control;
//private Text text;
private StackPane indicator;
private StackPane progress;
private StackPane tick;
private Arc arcShape;
private Circle indicatorCircle;
public DeterminateIndicator(ConfidenceProgressIndicator control, ConfidenceProgressIndicatorSkin s, Paint fillOverride)
{
this.control = control;
getStyleClass().add("determinate-indicator");
intProgress = (int) Math.round(control.getProgress() * 100.0);
degProgress = (int) (360 * control.getProgress());
InvalidationListener progressListener = new InvalidationListener()
{
@Override
public void invalidated(Observable valueModel)
{
updateProgress();
}
};
control.progressProperty().addListener(progressListener);
getChildren().clear();
/* text = new Text((control.getProgress() >= 1) ? (DONE) : ("" + intProgress + "%"));
text.setTextOrigin(VPos.TOP);
text.getStyleClass().setAll("text", "percentage"); */
// The circular background for the progress pie piece
indicator = new StackPane();
indicator.setScaleShape(false);
indicator.setCenterShape(false);
indicator.getStyleClass().setAll("indicator");
indicatorCircle = new Circle();
indicator.setShape(indicatorCircle);
// The shape for our progress pie piece
arcShape = new Arc();
arcShape.setType(ArcType.ROUND);
arcShape.setStartAngle(90.0F);
// Our progress pie piece
progress = new StackPane();
progress.getStyleClass().setAll("progress");
progress.setScaleShape(false);
progress.setCenterShape(false);
progress.setShape(arcShape);
progress.getChildren().clear();
setFillOverride(fillOverride);
// The check mark that's drawn at 100%
tick = new StackPane();
tick.getStyleClass().setAll("tick");
getChildren().setAll(indicator, progress, /*text,*/ tick);
updateProgress();
}
private void setFillOverride(Paint fillOverride)
{
if (fillOverride instanceof Color)
{
Color c = (Color) fillOverride;
progress.setStyle("-fx-background-color: rgba(" + ((int) (255 * c.getRed())) + "," + ((int) (255 * c.getGreen())) + "," + ((int) (255 * c.getBlue())) + "," + c.getOpacity() + ");");
}
else
{
progress.setStyle(null);
}
}
//@Override
public boolean isAutomaticallyMirrored()
{
// This is used instead of setting NodeOrientation,
// allowing the Text node to inherit the current
// orientation.
return false;
}
private void updateProgress()
{
intProgress = (int) Math.round(control.getProgress() * 100.0);
// text.setText((control.getProgress() >= 1) ? (DONE) : ("" + intProgress + "%"));
degProgress = (int) (360 * control.getProgress());
arcShape.setLength(-degProgress);
indicator.setOpacity(control.getProgress() == 0 ? 0.2 : 1);
requestLayout();
}
@Override
protected void layoutChildren()
{
// Position and size the circular background
//double doneTextHeight = doneText.getLayoutBounds().getHeight();
final Insets controlInsets = control.getInsets();
final double left = snapSize(controlInsets.getLeft());
final double right = snapSize(controlInsets.getRight());
final double top = snapSize(controlInsets.getTop());
final double bottom = snapSize(controlInsets.getBottom());
/*
** use the min of width, or height, keep it a circle
*/
final double areaW = control.getWidth() - left - right;
final double areaH = control.getHeight() - top - bottom /*- textGap - doneTextHeight*/;
final double radiusW = areaW / 2;
final double radiusH = areaH / 2;
final double radius = Math.floor(Math.min(radiusW, radiusH));
final double centerX = snapPosition(left + radiusW);
final double centerY = snapPosition(top + radius);
// find radius that fits inside radius - insetsPadding
final Insets indicatorInsets = indicator.getInsets();
final double iLeft = snapSize(indicatorInsets.getLeft());
final double iRight = snapSize(indicatorInsets.getRight());
final double iTop = snapSize(indicatorInsets.getTop());
final double iBottom = snapSize(indicatorInsets.getBottom());
final double progressRadius = snapSize(Math.min(
Math.min(radius - iLeft, radius - iRight),
Math.min(radius - iTop, radius - iBottom)));
indicatorCircle.setRadius(radius);
indicator.setLayoutX(centerX);
indicator.setLayoutY(centerY);
arcShape.setRadiusX(progressRadius);
arcShape.setRadiusY(progressRadius);
progress.setLayoutX(centerX);
progress.setLayoutY(centerY);
// find radius that fits inside progressRadius - progressInsets
final Insets progressInsets = progress.getInsets();
final double pLeft = snapSize(progressInsets.getLeft());
final double pRight = snapSize(progressInsets.getRight());
final double pTop = snapSize(progressInsets.getTop());
final double pBottom = snapSize(progressInsets.getBottom());
final double indicatorRadius = snapSize(Math.min(
Math.min(progressRadius - pLeft, progressRadius - pRight),
Math.min(progressRadius - pTop, progressRadius - pBottom)));
// find size of spare box that fits inside indicator radius
double squareBoxHalfWidth = Math.ceil(Math.sqrt((indicatorRadius * indicatorRadius) / 2));
// double squareBoxHalfWidth2 = indicatorRadius * (Math.sqrt(2) / 2);
tick.setLayoutX(centerX - squareBoxHalfWidth);
tick.setLayoutY(centerY - squareBoxHalfWidth);
tick.resize(squareBoxHalfWidth + squareBoxHalfWidth, squareBoxHalfWidth + squareBoxHalfWidth);
tick.setVisible(control.getProgress() >= 1);
// if the % text can't fit anywhere in the bounds then don't display it
/* double textWidth = text.getLayoutBounds().getWidth();
double textHeight = text.getLayoutBounds().getHeight();
if (control.getWidth() >= textWidth && control.getHeight() >= textHeight) {
if (!text.isVisible()) text.setVisible(true);
text.setLayoutY(snapPosition(centerY + radius + textGap));
text.setLayoutX(snapPosition(centerX - (textWidth/2)));
} else {
if (text.isVisible()) text.setVisible(false);
} */
}
@Override
protected double computePrefWidth(double height)
{
final Insets controlInsets = control.getInsets();
final double left = snapSize(controlInsets.getLeft());
final double right = snapSize(controlInsets.getRight());
final Insets indicatorInsets = indicator.getInsets();
final double iLeft = snapSize(indicatorInsets.getLeft());
final double iRight = snapSize(indicatorInsets.getRight());
final double iTop = snapSize(indicatorInsets.getTop());
final double iBottom = snapSize(indicatorInsets.getBottom());
final double indicatorMax = snapSize(Math.max(Math.max(iLeft, iRight), Math.max(iTop, iBottom)));
final Insets progressInsets = progress.getInsets();
final double pLeft = snapSize(progressInsets.getLeft());
final double pRight = snapSize(progressInsets.getRight());
final double pTop = snapSize(progressInsets.getTop());
final double pBottom = snapSize(progressInsets.getBottom());
final double progressMax = snapSize(Math.max(Math.max(pLeft, pRight), Math.max(pTop, pBottom)));
final Insets tickInsets = tick.getInsets();
final double tLeft = snapSize(tickInsets.getLeft());
final double tRight = snapSize(tickInsets.getRight());
final double indicatorWidth = indicatorMax + progressMax + tLeft + tRight + progressMax + indicatorMax;
return left + indicatorWidth + /*Math.max(indicatorWidth, doneText.getLayoutBounds().getWidth()) + */right;
}
@Override
protected double computePrefHeight(double width)
{
final Insets controlInsets = control.getInsets();
final double top = snapSize(controlInsets.getTop());
final double bottom = snapSize(controlInsets.getBottom());
final Insets indicatorInsets = indicator.getInsets();
final double iLeft = snapSize(indicatorInsets.getLeft());
final double iRight = snapSize(indicatorInsets.getRight());
final double iTop = snapSize(indicatorInsets.getTop());
final double iBottom = snapSize(indicatorInsets.getBottom());
final double indicatorMax = snapSize(Math.max(Math.max(iLeft, iRight), Math.max(iTop, iBottom)));
final Insets progressInsets = progress.getInsets();
final double pLeft = snapSize(progressInsets.getLeft());
final double pRight = snapSize(progressInsets.getRight());
final double pTop = snapSize(progressInsets.getTop());
final double pBottom = snapSize(progressInsets.getBottom());
final double progressMax = snapSize(Math.max(Math.max(pLeft, pRight), Math.max(pTop, pBottom)));
final Insets tickInsets = tick.getInsets();
final double tTop = snapSize(tickInsets.getTop());
final double tBottom = snapSize(tickInsets.getBottom());
final double indicatorHeight = indicatorMax + progressMax + tTop + tBottom + progressMax + indicatorMax;
return top + indicatorHeight /*+ textGap + doneText.getLayoutBounds().getHeight()*/ + bottom;
}
@Override
protected double computeMaxWidth(double height)
{
return computePrefWidth(height);
}
@Override
protected double computeMaxHeight(double width)
{
return computePrefHeight(width);
}
}
/**
* ************************************************************************
* *
* IndeterminateSpinner *
* *
* ************************************************************************
*/
static class IndeterminateSpinner extends Region
{
private ConfidenceProgressIndicator control;
private ConfidenceProgressIndicatorSkin skin;
private IndicatorPaths pathsG;
private Timeline indeterminateTimeline;
private final List<Double> opacities = new ArrayList<Double>();
private boolean spinEnabled = false;
private Paint fillOverride = null;
public IndeterminateSpinner(ConfidenceProgressIndicator control, ConfidenceProgressIndicatorSkin s, boolean spinEnabled, Paint fillOverride)
{
this.control = control;
this.skin = s;
this.spinEnabled = spinEnabled;
this.fillOverride = fillOverride;
setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT);
getStyleClass().setAll("spinner");
pathsG = new IndicatorPaths(this);
getChildren().add(pathsG);
indeterminateTimeline = new Timeline();
indeterminateTimeline.setCycleCount(Timeline.INDEFINITE);
rebuildTimeline();
rebuild();
}
public void setFillOverride(Paint fillOverride)
{
this.fillOverride = fillOverride;
rebuild();
}
public void setSpinEnabled(boolean spinEnabled)
{
this.spinEnabled = spinEnabled;
rebuildTimeline();
}
private void rebuildTimeline()
{
final ObservableList<KeyFrame> keyFrames = FXCollections.<KeyFrame>observableArrayList();
if (spinEnabled)
{
keyFrames.add(new KeyFrame(Duration.millis(0), new KeyValue(pathsG.rotateProperty(), 360)));
keyFrames.add(new KeyFrame(Duration.millis(3900), new KeyValue(pathsG.rotateProperty(), 0)));
}
for (int i = 100; i <= 3900; i += 100)
{
keyFrames.add(
new KeyFrame(
Duration.millis(i), new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
shiftColors();
}
}));
}
indeterminateTimeline.getKeyFrames().setAll(keyFrames);
}
private void pauseIndicator(boolean pause)
{
if (indeterminateTimeline != null)
{
if (pause)
{
indeterminateTimeline.pause();
}
else
{
indeterminateTimeline.play();
}
}
}
private class IndicatorPaths extends Pane
{
IndeterminateSpinner piSkin;
IndicatorPaths(IndeterminateSpinner pi)
{
super();
piSkin = pi;
InvalidationListener treeVisibilityListener = new InvalidationListener()
{
@Override
public void invalidated(Observable valueModel)
{
if (piSkin.skin.getSkinnable().impl_isTreeVisible())
{
piSkin.pauseIndicator(false);
}
else
{
piSkin.pauseIndicator(true);
}
}
};
impl_treeVisibleProperty().addListener(treeVisibilityListener);
}
@Override
protected double computePrefWidth(double height)
{
double w = 0;
for (Node child : getChildren())
{
if (child instanceof Region)
{
Region region = (Region) child;
if (region.getShape() != null)
{
w = Math.max(w, region.getShape().getLayoutBounds().getMaxX());
}
else
{
w = Math.max(w, region.prefWidth(height));
}
}
}
return w;
}
@Override
protected double computePrefHeight(double width)
{
double h = 0;
for (Node child : getChildren())
{
if (child instanceof Region)
{
Region region = (Region) child;
if (region.getShape() != null)
{
h = Math.max(h, region.getShape().getLayoutBounds().getMaxY());
}
else
{
h = Math.max(h, region.prefHeight(width));
}
}
}
return h;
}
@Override
protected void layoutChildren()
{
// calculate scale
double scale = getWidth() / computePrefWidth(-1);
for (Node child : getChildren())
{
if (child instanceof Region)
{
Region region = (Region) child;
if (region.getShape() != null)
{
region.resize(
region.getShape().getLayoutBounds().getMaxX(),
region.getShape().getLayoutBounds().getMaxY()
);
region.getTransforms().setAll(new Scale(scale, scale, 0, 0));
}
else
{
region.autosize();
}
}
}
}
}
@Override
protected void layoutChildren()
{
Insets controlInsets = control.getInsets();
final double w = control.getWidth() - controlInsets.getLeft() - controlInsets.getRight();
final double h = control.getHeight() - controlInsets.getTop() - controlInsets.getBottom();
final double prefW = pathsG.prefWidth(-1);
final double prefH = pathsG.prefHeight(-1);
double scaleX = w / prefW;
double scale = scaleX;
if ((scaleX * prefH) > h)
{
scale = h / prefH;
}
double indicatorW = prefW * scale - 3;
double indicatorH = prefH * scale - 3;
pathsG.resizeRelocate((w - indicatorW) / 2, (h - indicatorH) / 2, indicatorW, indicatorH);
}
private void rebuild()
{
// update indeterminate indicator
final int segments = skin.indeterminateSegmentCount.get();
opacities.clear();
pathsG.getChildren().clear();
final double step = 0.8 / (segments - 1);
for (int i = 0; i < segments; i++)
{
Region region = new Region();
region.setScaleShape(false);
region.setCenterShape(false);
region.getStyleClass().addAll("segment", "segment" + i);
if (fillOverride instanceof Color)
{
Color c = (Color) fillOverride;
region.setStyle("-fx-background-color: rgba(" + ((int) (255 * c.getRed())) + "," + ((int) (255 * c.getGreen())) + "," + ((int) (255 * c.getBlue())) + "," + c.getOpacity() + ");");
}
else
{
region.setStyle(null);
}
pathsG.getChildren().add(region);
opacities.add(Math.min(1, 0.2 + (i * step)));
}
}
private void shiftColors()
{
if (opacities.size() <= 0) return;
final int segments = skin.indeterminateSegmentCount.get();
Collections.rotate(opacities, -1);
for (int i = 0; i < segments; i++)
{
pathsG.getChildren().get(i).setOpacity(opacities.get(i));
}
}
}
public Paint getProgressColor()
{
return progressColor.get();
}
/**
* The colour of the progress segment.
*/
private ObjectProperty<Paint> progressColor =
new StyleableObjectProperty<Paint>(null)
{
@Override
public void set(Paint newProgressColor)
{
final Paint color = (newProgressColor instanceof Color)
? newProgressColor
: null;
super.set(color);
}
@Override
protected void invalidated()
{
if (spinner != null) spinner.setFillOverride(get());
if (determinateIndicator != null) determinateIndicator.setFillOverride(get());
}
@Override
public Object getBean()
{
return ConfidenceProgressIndicatorSkin.this;
}
@Override
public String getName()
{
return "progressColorProperty";
}
@Override
public CssMetaData<ConfidenceProgressIndicator, Paint> getCssMetaData()
{
return StyleableProperties.PROGRESS_COLOR;
}
};
/**
* The number of segments in the spinner.
*/
private IntegerProperty indeterminateSegmentCount =
new StyleableIntegerProperty(8)
{
@Override
protected void invalidated()
{
if (spinner != null) spinner.rebuild();
}
@Override
public Object getBean()
{
return ConfidenceProgressIndicatorSkin.this;
}
@Override
public String getName()
{
return "indeterminateSegmentCount";
}
@Override
public CssMetaData<ConfidenceProgressIndicator, Number> getCssMetaData()
{
return StyleableProperties.INDETERMINATE_SEGMENT_COUNT;
}
};
/**
* True if the progress indicator should rotate as well as animate opacity.
*/
private final BooleanProperty spinEnabled = new StyleableBooleanProperty(false)
{
@Override
protected void invalidated()
{
if (spinner != null) spinner.setSpinEnabled(get());
}
@Override
public CssMetaData<ConfidenceProgressIndicator, Boolean> getCssMetaData()
{
return StyleableProperties.SPIN_ENABLED;
}
@Override
public Object getBean()
{
return ConfidenceProgressIndicatorSkin.this;
}
@Override
public String getName()
{
return "spinEnabled";
}
};
// *********** Stylesheet Handling *****************************************
/**
* Super-lazy instantiation pattern from Bill Pugh.
*
* @treatAsPrivate implementation detail
*/
private static class StyleableProperties
{
private static final CssMetaData<ConfidenceProgressIndicator, Paint> PROGRESS_COLOR =
new CssMetaData<ConfidenceProgressIndicator, Paint>("-fx-progress-color",
PaintConverter.getInstance(), null)
{
@Override
public boolean isSettable(ConfidenceProgressIndicator n)
{
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
return skin.progressColor == null ||
!skin.progressColor.isBound();
}
@Override
public StyleableProperty<Paint> getStyleableProperty(ConfidenceProgressIndicator n)
{
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
return (StyleableProperty<Paint>) skin.progressColor;
}
};
private static final CssMetaData<ConfidenceProgressIndicator, Number> INDETERMINATE_SEGMENT_COUNT =
new CssMetaData<ConfidenceProgressIndicator, Number>("-fx-indeterminate-segment-count",
SizeConverter.getInstance(), 8)
{
@Override
public void set(ConfidenceProgressIndicator node, Number value, StyleOrigin origin)
{
super.set(node, value.intValue(), origin);
}
@Override
public boolean isSettable(ConfidenceProgressIndicator n)
{
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
return skin.indeterminateSegmentCount == null ||
!skin.indeterminateSegmentCount.isBound();
}
@Override
public StyleableProperty<Number> getStyleableProperty(ConfidenceProgressIndicator n)
{
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) n.getSkin();
return (StyleableProperty<Number>) skin.indeterminateSegmentCount;
}
};
private static final CssMetaData<ConfidenceProgressIndicator, Boolean> SPIN_ENABLED =
new CssMetaData<ConfidenceProgressIndicator, Boolean>("-fx-spin-enabled",
BooleanConverter.getInstance(), Boolean.FALSE)
{
@Override
public boolean isSettable(ConfidenceProgressIndicator node)
{
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) node.getSkin();
return skin.spinEnabled == null || !skin.spinEnabled.isBound();
}
@Override
public StyleableProperty<Boolean> getStyleableProperty(ConfidenceProgressIndicator node)
{
final ConfidenceProgressIndicatorSkin skin = (ConfidenceProgressIndicatorSkin) node.getSkin();
return (StyleableProperty<Boolean>) skin.spinEnabled;
}
};
public static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
static
{
final List<CssMetaData<? extends Styleable, ?>> styleables =
new ArrayList<CssMetaData<? extends Styleable, ?>>(SkinBase.getClassCssMetaData());
styleables.add(PROGRESS_COLOR);
styleables.add(INDETERMINATE_SEGMENT_COUNT);
styleables.add(SPIN_ENABLED);
STYLEABLES = Collections.unmodifiableList(styleables);
}
}
/**
* @return The CssMetaData associated with this class, which may include the
* CssMetaData of its super classes.
*/
public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData()
{
return StyleableProperties.STYLEABLES;
}
/**
* {@inheritDoc}
*/
@Override
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData()
{
return getClassCssMetaData();
}
}

View file

@ -1,10 +1,10 @@
package io.bitsquare.gui.components.processbar; package io.bitsquare.gui.components.processbar;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.scene.control.Button; import javafx.scene.control.Button;
import javafx.scene.control.Control; import javafx.scene.control.Control;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import java.util.ArrayList; import java.util.ArrayList;
@ -57,7 +57,7 @@ public class ProcessStepsBuilder
if (processStepItem.hasProgressIndicator()) if (processStepItem.hasProgressIndicator())
{ {
final ProgressIndicator progressIndicator = new ProgressIndicator(); final ConfidenceProgressIndicator progressIndicator = new ConfidenceProgressIndicator();
progressIndicator.setProgress(-1.0); progressIndicator.setProgress(-1.0);
progressIndicator.setPrefSize(30.0, 30.0); progressIndicator.setPrefSize(30.0, 30.0);
controlHolder.getChildren().add(progressIndicator); controlHolder.getChildren().add(progressIndicator);

View file

@ -0,0 +1,47 @@
package io.bitsquare.gui.funds;
import com.google.bitcoin.core.Address;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class AddressListItem
{
private final StringProperty label = new SimpleStringProperty();
private final StringProperty addressString = new SimpleStringProperty();
private final BooleanProperty isUsed = new SimpleBooleanProperty();
private Address address;
public AddressListItem(String label, Address address, boolean isUsed)
{
this.address = address;
this.label.set(label);
this.addressString.set(address.toString());
this.isUsed.set(isUsed);
}
// called form table columns
public final StringProperty labelProperty()
{
return this.label;
}
public final StringProperty addressStringProperty()
{
return this.addressString;
}
public final BooleanProperty isUsedProperty()
{
return this.isUsed;
}
public Address getAddress()
{
return address;
}
}

View file

@ -1,39 +1,58 @@
package io.bitsquare.gui.funds; package io.bitsquare.gui.funds;
import com.google.bitcoin.core.Address;
import com.google.bitcoin.core.TransactionConfidence;
import com.google.bitcoin.core.Utils;
import com.google.inject.Inject; import com.google.inject.Inject;
import de.jensd.fx.fontawesome.AwesomeDude; import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.fontawesome.AwesomeIcon;
import io.bitsquare.btc.BalanceListener;
import io.bitsquare.btc.ConfidenceListener;
import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.ConfidenceDisplay; import io.bitsquare.gui.util.ConfidenceDisplay;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.Label; import javafx.scene.control.*;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.input.Clipboard; import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent; import javafx.scene.input.ClipboardContent;
import javafx.util.Callback;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class FundsController implements Initializable, ChildController public class FundsController implements Initializable, ChildController
{ {
private static final Logger log = LoggerFactory.getLogger(FundsController.class); private static final Logger log = LoggerFactory.getLogger(FundsController.class);
private WalletFacade walletFacade; private WalletFacade walletFacade;
private ConfidenceDisplay confidenceDisplay; private ConfidenceDisplay confidenceDisplay;
protected ObservableList<AddressListItem> addressList = FXCollections.observableArrayList();
@FXML @FXML
private TextField tradingAccountTextField, balanceTextField; private TableView addressesTable;
@FXML @FXML
private Label copyIcon, confirmationLabel; private TableColumn<String, AddressListItem> labelColumn, addressColumn, balanceColumn, copyColumn, confidenceColumn;
@FXML @FXML
private ProgressIndicator progressIndicator; private Button addNewAddressButton;
@FXML
private TextField labelTextField;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public FundsController(WalletFacade walletFacade) public FundsController(WalletFacade walletFacade)
@ -41,25 +60,42 @@ public class FundsController implements Initializable, ChildController
this.walletFacade = walletFacade; this.walletFacade = walletFacade;
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
public void initialize(URL url, ResourceBundle rb) public void initialize(URL url, ResourceBundle rb)
{ {
String tradingAccountAddress = walletFacade.getTradingAddress(); setBalanceColumnCellFactory();
tradingAccountTextField.setText(tradingAccountAddress); setCopyColumnCellFactory();
setConfidenceColumnCellFactory();
copyIcon.setId("copy-icon"); List<Address> addresses = walletFacade.getTradingAddresses();
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard"));
copyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(tradingAccountAddress);
clipboard.setContent(content);
});
confidenceDisplay = new ConfidenceDisplay(walletFacade.getWallet(), confirmationLabel, balanceTextField, progressIndicator); for (int i = 0; i < addresses.size(); i++)
{
Address address = addresses.get(i);
String label;
if (i == 0)
label = "Registration";
else
label = "Trade " + i;
addressList.add(new AddressListItem(label, address, false));
}
addressesTable.setItems(addressList);
addressesTable.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
//Platform.runLater(() -> walletFacade.triggerConfidenceNotificationForAllTransactions());
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
public void setNavigationController(NavigationController navigationController) public void setNavigationController(NavigationController navigationController)
{ {
@ -70,5 +106,198 @@ public class FundsController implements Initializable, ChildController
{ {
} }
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
@FXML
public void onAddNewAddress(ActionEvent actionEvent)
{
Address address = walletFacade.createNewAddress();
addressList.add(new AddressListItem("Trade " + (walletFacade.getTradingAddresses().size() - 1), address, false));
// walletFacade.triggerConfidenceNotificationForAllTransactions();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
private void setBalanceColumnCellFactory()
{
balanceColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper(addressListItem.getValue()));
balanceColumn.setCellFactory(new Callback<TableColumn<String, AddressListItem>, TableCell<String, AddressListItem>>()
{
@Override
public TableCell<String, AddressListItem> call(TableColumn<String, AddressListItem> column)
{
return new TableCell<String, AddressListItem>()
{
Label balanceLabel;
BalanceListener balanceListener;
@Override
public void updateItem(final AddressListItem item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
balanceListener = new BalanceListener(item.getAddress());
balanceLabel = new Label();
walletFacade.addBalanceListener(new BalanceListener(item.getAddress())
{
@Override
public void onBalanceChanged(BigInteger balance)
{
updateBalance(balance, balanceLabel);
}
});
updateBalance(walletFacade.getBalance(item.getAddress()), balanceLabel);
setGraphic(balanceLabel);
}
else
{
if (balanceListener != null)
walletFacade.removeBalanceListener(balanceListener);
setGraphic(null);
}
}
};
}
});
}
private void setCopyColumnCellFactory()
{
copyColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper(addressListItem.getValue()));
copyColumn.setCellFactory(new Callback<TableColumn<String, AddressListItem>, TableCell<String, AddressListItem>>()
{
@Override
public TableCell<String, AddressListItem> call(TableColumn<String, AddressListItem> column)
{
return new TableCell<String, AddressListItem>()
{
Label copyIcon = new Label();
{
copyIcon.setId("copy-icon");
AwesomeDude.setIcon(copyIcon, AwesomeIcon.COPY);
Tooltip.install(copyIcon, new Tooltip("Copy address to clipboard"));
}
@Override
public void updateItem(final AddressListItem item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
setGraphic(copyIcon);
copyIcon.setOnMouseClicked(e -> {
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(item.addressStringProperty().get());
clipboard.setContent(content);
});
}
else
{
setGraphic(null);
}
}
};
}
});
}
private void setConfidenceColumnCellFactory()
{
confidenceColumn.setCellValueFactory((addressListItem) -> new ReadOnlyObjectWrapper(addressListItem.getValue()));
confidenceColumn.setCellFactory(new Callback<TableColumn<String, AddressListItem>, TableCell<String, AddressListItem>>()
{
@Override
public TableCell<String, AddressListItem> call(TableColumn<String, AddressListItem> column)
{
return new TableCell<String, AddressListItem>()
{
ConfidenceListener confidenceListener;
ConfidenceProgressIndicator progressIndicator;
@Override
public void updateItem(final AddressListItem item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
progressIndicator = new ConfidenceProgressIndicator();
Tooltip tooltip = new Tooltip("Not used yet");
progressIndicator.setProgress(0);
progressIndicator.setPrefHeight(30);
progressIndicator.setPrefWidth(30);
Tooltip.install(progressIndicator, tooltip);
confidenceListener = new ConfidenceListener(item.getAddress());
walletFacade.addConfidenceListener(new ConfidenceListener(item.getAddress())
{
@Override
public void onTransactionConfidenceChanged(TransactionConfidence confidence)
{
updateConfidence(confidence, progressIndicator, tooltip);
}
});
updateConfidence(walletFacade.getConfidence(item.getAddress()), progressIndicator, tooltip);
setGraphic(progressIndicator);
}
else
{
if (confidenceListener != null)
walletFacade.removeConfidenceListener(confidenceListener);
setGraphic(null);
}
}
};
}
});
}
private void updateBalance(BigInteger balance, Label balanceLabel)
{
if (balance != null)
balanceLabel.setText(Utils.bitcoinValueToFriendlyString(balance));
}
private void updateConfidence(TransactionConfidence confidence, ConfidenceProgressIndicator progressIndicator, Tooltip tooltip)
{
if (confidence != null)
{
switch (confidence.getConfidenceType())
{
case UNKNOWN:
tooltip.setText("Unknown transaction status");
progressIndicator.setProgress(0);
break;
case PENDING:
tooltip.setText("Seen by " + confidence.numBroadcastPeers() + " peer(s) / 0 confirmations");
progressIndicator.setProgress(-1.0);
break;
case BUILDING:
tooltip.setText("Confirmed in " + confidence.getDepthInBlocks() + " block(s)");
progressIndicator.setProgress(Math.min(1, (double) confidence.getDepthInBlocks() / 6.0));
break;
case DEAD:
tooltip.setText("Transaction is invalid.");
break;
}
}
}
} }

View file

@ -1,58 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<AnchorPane fx:controller="io.bitsquare.gui.funds.FundsController" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0" <AnchorPane prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
xmlns:fx="http://javafx.com/fxml"> xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.bitsquare.gui.funds.FundsController">
<children>
<VBox spacing="20" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Label id="headline-label" text="Trading account wallet"/> <TabPane fx:id="tabPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<GridPane hgap="5.0" vgap="5.0"> <Tab text="Deposit" closable="false">
<VBox spacing="10">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<TableView fx:id="addressesTable" id="orderbook-table">
<columns>
<TableColumn text="Label" fx:id="labelColumn" minWidth="100" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="label"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Address" fx:id="addressColumn" minWidth="240" sortable="false">
<cellValueFactory>
<PropertyValueFactory property="address"/>
</cellValueFactory>
</TableColumn>
<TableColumn text="Balance" fx:id="balanceColumn" minWidth="50" sortable="false"/>
<TableColumn text="Copy" fx:id="copyColumn" minWidth="30" sortable="false"/>
<TableColumn text="Status" fx:id="confidenceColumn" minWidth="30" sortable="false"/>
<children> </columns>
<Label text="Trading account address:"/> </TableView>
<TextField fx:id="tradingAccountTextField" editable="false" GridPane.columnIndex="1"/>
<Label fx:id="copyIcon" GridPane.columnIndex="2">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
<tooltip>
<Tooltip text="Copy address to clipboard"/>
</tooltip>
</Label>
<Label text="Balance:" GridPane.rowIndex="1"/> <Button fx:id="addNewAddressButton" text="Add new address" onAction="#onAddNewAddress"/>
<TextField fx:id="balanceTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/> </VBox>
<ProgressIndicator fx:id="progressIndicator" id="confidence-progress-indicator" GridPane.columnIndex="2" GridPane.halignment="LEFT" </Tab>
GridPane.rowIndex="1" GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin> <Tab text="Withdrawal" closable="false">
<Insets top="2.0"/> <GridPane hgap="5.0" vgap="5.0">
</GridPane.margin> <padding>
</ProgressIndicator> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
<Label fx:id="confirmationLabel" text="Checking confirmations..." GridPane.columnIndex="3" GridPane.rowIndex="1"/> </padding>
<children>
<Label text="Trading account address:"/>
<TextField fx:id="tradingAccountTextField2" editable="false" GridPane.columnIndex="1"/>
<Label fx:id="copyIcon2" GridPane.columnIndex="2">
<padding>
<Insets bottom="0.0" left="0.0" right="0.0" top="-1.0"/>
</padding>
<tooltip>
<Tooltip text="Copy address to clipboard"/>
</tooltip>
</Label>
<Label text="Balance:" GridPane.rowIndex="1"/>
<TextField fx:id="balanceTextField2" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<ConfidenceProgressIndicator fx:id="progressIndicator2" GridPane.columnIndex="2" GridPane.halignment="LEFT"
GridPane.rowIndex="1" GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin>
<Insets top="2.0"/>
</GridPane.margin>
</ConfidenceProgressIndicator>
<Label fx:id="confirmationLabel2" text="Checking confirmations..." GridPane.columnIndex="3" GridPane.rowIndex="1"/>
<Label text="dummy for layout progressIndicator" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="2"/> <Label text="dummy for layout progressIndicator" visible="false" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
</children> </children>
<columnConstraints> <columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES"/> <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="ALWAYS"/> <ColumnConstraints hgrow="ALWAYS"/>
<ColumnConstraints hgrow="SOMETIMES" prefWidth="20.0" minWidth="20.0"/> <ColumnConstraints hgrow="SOMETIMES" prefWidth="20.0" minWidth="20.0"/>
<ColumnConstraints hgrow="SOMETIMES"/> <ColumnConstraints hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="SOMETIMES"/> <ColumnConstraints hgrow="SOMETIMES"/>
</columnConstraints> </columnConstraints>
<rowConstraints> <rowConstraints>
<RowConstraints vgrow="SOMETIMES"/> <RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES"/> <RowConstraints vgrow="SOMETIMES"/>
<RowConstraints vgrow="SOMETIMES"/> <RowConstraints vgrow="SOMETIMES"/>
</rowConstraints> </rowConstraints>
</GridPane> </GridPane>
</children> </Tab>
</VBox>
</children> </TabPane>
</AnchorPane> </AnchorPane>

View file

@ -23,13 +23,9 @@
-fx-fill: red; -fx-fill: red;
} }
#confidence-progress-indicator {
-fx-fill: null;
}
/* main nav */ /* main nav */
#nav-button { #nav-button {
-fx-cursor: hand;
-fx-background-color: transparent; -fx-background-color: transparent;
-fx-alignment: center; -fx-alignment: center;
} }
@ -78,6 +74,11 @@
-fx-underline: true; -fx-underline: true;
} }
#icon-button {
-fx-cursor: hand;
-fx-background-color: transparent;
}
/* table */ /* table */
#orderbook-table .table-cell { #orderbook-table .table-cell {

View file

@ -1,25 +1,37 @@
package io.bitsquare.gui.home; package io.bitsquare.gui.home;
import io.bitsquare.BitSquare;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.arbitrators.registration.ArbitratorRegistrationController;
import io.bitsquare.locale.Localisation;
import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class HomeController implements Initializable, ChildController public class HomeController implements Initializable, ChildController, NavigationController
{ {
private NavigationController navigationController; private NavigationController navigationController;
@FXML @FXML
public Pane rootContainer; public Pane rootContainer;
private ArbitratorRegistrationController arbitratorRegistrationController;
@Override @Override
public void initialize(URL url, ResourceBundle rb) public void initialize(URL url, ResourceBundle rb)
{ {
// navigateToView(NavigationController.ARBITRATOR_REGISTRATION, "Registration as Arbitrator");
} }
@Override @Override
@ -33,6 +45,67 @@ public class HomeController implements Initializable, ChildController
{ {
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: NavigationController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public ChildController navigateToView(String fxmlView)
{
return navigateToView(fxmlView, "");
}
@Override
public ChildController navigateToView(String fxmlView, String title)
{
if (arbitratorRegistrationController != null)
arbitratorRegistrationController.cleanup();
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
try
{
final Node view = loader.load();
arbitratorRegistrationController = loader.getController();
arbitratorRegistrationController.setNavigationController(this);
final Stage rootStage = BitSquare.getStage();
final Stage stage = new Stage();
stage.setTitle(title);
stage.setMinWidth(800);
stage.setMinHeight(400);
stage.setWidth(800);
stage.setHeight(600);
stage.setX(rootStage.getX() + 50);
stage.setY(rootStage.getY() + 50);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(rootStage);
Scene scene = new Scene((Parent) view, 800, 600);
stage.setScene(scene);
stage.show();
return arbitratorRegistrationController;
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
@FXML
public void onArbitratorRegistration(ActionEvent actionEvent)
{
navigateToView(NavigationController.ARBITRATOR_REGISTRATION, "Registration as Arbitrator");
}
@FXML
public void onArbitratorEdit(ActionEvent actionEvent)
{
navigateToView(NavigationController.ARBITRATOR_REGISTRATION, "Edit my arbitrator details");
arbitratorRegistrationController.setEditMode(true);
}
} }

View file

@ -1,3 +1,4 @@
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
<AnchorPane fx:controller="io.bitsquare.gui.home.HomeController" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0" <AnchorPane fx:controller="io.bitsquare.gui.home.HomeController" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0"
@ -7,6 +8,10 @@
<children> <children>
<Label id="headline-label" text="Overview"/> <Label id="headline-label" text="Overview"/>
<Label text="TODO"/>
<Button text="Register yourself as an arbitrator" onAction="#onArbitratorRegistration"/>
<Button text="Edit my arbitrator details" onAction="#onArbitratorEdit"/>
</children> </children>
</VBox> </VBox>

View file

@ -4,7 +4,7 @@ import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.market.orderbook.OrderBookController; import io.bitsquare.gui.market.orderbook.OrderBookController;
import io.bitsquare.gui.util.Localisation; import io.bitsquare.locale.Localisation;
import io.bitsquare.trade.Direction; import io.bitsquare.trade.Direction;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
@ -42,6 +42,12 @@ public class MarketController implements Initializable, NavigationController, Ch
// Interface implementation: NavigationController // Interface implementation: NavigationController
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Override
public ChildController navigateToView(String fxmlView)
{
return navigateToView(fxmlView, "");
}
@Override @Override
public ChildController navigateToView(String fxmlView, String title) public ChildController navigateToView(String fxmlView, String title)
{ {
@ -111,7 +117,8 @@ public class MarketController implements Initializable, NavigationController, Ch
public void setDirection(Direction direction) public void setDirection(Direction direction)
{ {
tabPane.getSelectionModel().select(0); tabPane.getSelectionModel().select(0);
orderBookController.setDirection(direction); if (orderBookController != null)
orderBookController.setDirection(direction);
} }
} }

View file

@ -10,7 +10,12 @@ import io.bitsquare.btc.Fees;
import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.util.*; import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.BitSquareConverter;
import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.gui.util.ConfidenceDisplay;
import io.bitsquare.gui.util.Popups;
import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.settings.Settings; import io.bitsquare.settings.Settings;
import io.bitsquare.trade.Direction; import io.bitsquare.trade.Direction;
@ -24,7 +29,10 @@ import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.scene.control.*; import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -32,6 +40,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.util.Random;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class CreateOfferController implements Initializable, ChildController public class CreateOfferController implements Initializable, ChildController
@ -60,7 +69,7 @@ public class CreateOfferController implements Initializable, ChildController
private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField, private TextField collateralTextField, minAmountTextField, bankAccountTypeTextField, bankAccountCurrencyTextField, bankAccountCountyTextField,
acceptedCountriesTextField, acceptedLanguagesTextField, feeLabel, txTextField; acceptedCountriesTextField, acceptedLanguagesTextField, feeLabel, txTextField;
@FXML @FXML
private ProgressIndicator progressIndicator; private ConfidenceProgressIndicator progressIndicator;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -85,17 +94,17 @@ public class CreateOfferController implements Initializable, ChildController
public void setOrderBookFilter(OrderBookFilter orderBookFilter) public void setOrderBookFilter(OrderBookFilter orderBookFilter)
{ {
direction = orderBookFilter.getDirection(); direction = orderBookFilter.getDirection();
amountTextField.setText(Formatter.formatPrice(orderBookFilter.getAmount())); amountTextField.setText(BitSquareFormatter.formatPrice(orderBookFilter.getAmount()));
minAmountTextField.setText(Formatter.formatPrice(orderBookFilter.getAmount())); minAmountTextField.setText(BitSquareFormatter.formatPrice(orderBookFilter.getAmount()));
priceTextField.setText(Formatter.formatPrice(orderBookFilter.getPrice())); priceTextField.setText(BitSquareFormatter.formatPrice(orderBookFilter.getPrice()));
buyLabel.setText(Formatter.formatDirection(direction, false) + ":"); buyLabel.setText(BitSquareFormatter.formatDirection(direction, false) + ":");
collateralTextField.setText(Formatter.formatVolume(settings.getMinCollateral())); collateralTextField.setText(BitSquareFormatter.formatVolume(settings.getMinCollateral()));
updateVolume(); updateVolume();
//TODO //TODO
/* amountTextField.setText(""+(int)(new Random().nextDouble()*100/10+1)); amountTextField.setText("" + (int) (new Random().nextDouble() * 100 / 10 + 1));
priceTextField.setText(""+ (int)(499 - new Random().nextDouble()*1000/100)); */ priceTextField.setText("" + (int) (499 - new Random().nextDouble() * 1000 / 100));
minAmountTextField.setText("0,1"); minAmountTextField.setText("0,1");
collateralTextField.setText("10"); collateralTextField.setText("10");
updateVolume(); updateVolume();
@ -127,11 +136,11 @@ public class CreateOfferController implements Initializable, ChildController
@Override @Override
public void initialize(URL url, ResourceBundle rb) public void initialize(URL url, ResourceBundle rb)
{ {
bankAccountTypeTextField.setText(Localisation.get(user.getCurrentBankAccount().getBankAccountType().getType().toString())); bankAccountTypeTextField.setText(Localisation.get(user.getCurrentBankAccount().getBankAccountTypeInfo().getType().toString()));
bankAccountCurrencyTextField.setText(user.getCurrentBankAccount().getCurrency().getCurrencyCode()); bankAccountCurrencyTextField.setText(user.getCurrentBankAccount().getCurrency().getCurrencyCode());
bankAccountCountyTextField.setText(user.getCurrentBankAccount().getCountryLocale().getDisplayCountry()); bankAccountCountyTextField.setText(user.getCurrentBankAccount().getCountry().getName());
acceptedCountriesTextField.setText(Formatter.countryLocalesToString(settings.getAcceptedCountryLocales())); acceptedCountriesTextField.setText(BitSquareFormatter.countryLocalesToString(settings.getAcceptedCountries()));
acceptedLanguagesTextField.setText(Formatter.languageLocalesToString(settings.getAcceptedLanguageLocales())); acceptedLanguagesTextField.setText(BitSquareFormatter.languageLocalesToString(settings.getAcceptedLanguageLocales()));
feeLabel.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE)); feeLabel.setText(Utils.bitcoinValueToFriendlyString(Fees.OFFER_CREATION_FEE));
} }
@ -164,7 +173,7 @@ public class CreateOfferController implements Initializable, ChildController
return; return;
} }
int collateral = (int) (Converter.stringToDouble(collateralTextField.getText())); int collateral = (int) (BitSquareConverter.stringToDouble2(collateralTextField.getText()));
Arbitrator arbitrator = settings.getRandomArbitrator(collateral, getAmountAsBI()); Arbitrator arbitrator = settings.getRandomArbitrator(collateral, getAmountAsBI());
if (arbitrator == null) if (arbitrator == null)
{ {
@ -176,16 +185,16 @@ public class CreateOfferController implements Initializable, ChildController
offer = new Offer(user.getMessagePubKeyAsHex(), offer = new Offer(user.getMessagePubKeyAsHex(),
direction, direction,
Converter.stringToDouble(priceTextField.getText()), BitSquareConverter.stringToDouble2(priceTextField.getText()),
BtcFormatter.stringValueToSatoshis(amountTextField.getText()), BtcFormatter.stringValueToSatoshis(amountTextField.getText()),
BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()), BtcFormatter.stringValueToSatoshis(minAmountTextField.getText()),
user.getCurrentBankAccount().getBankAccountType().getType(), user.getCurrentBankAccount().getBankAccountTypeInfo().getType(),
user.getCurrentBankAccount().getCurrency(), user.getCurrentBankAccount().getCurrency(),
user.getCurrentBankAccount().getCountryLocale(), user.getCurrentBankAccount().getCountry(),
user.getCurrentBankAccount().getUid(), user.getCurrentBankAccount().getUid(),
arbitrator, arbitrator,
collateral, collateral,
settings.getAcceptedCountryLocales(), settings.getAcceptedCountries(),
settings.getAcceptedLanguageLocales()); settings.getAcceptedLanguageLocales());
FutureCallback callback = new FutureCallback<Transaction>() FutureCallback callback = new FutureCallback<Transaction>()
@ -255,13 +264,13 @@ public class CreateOfferController implements Initializable, ChildController
private void updateVolume() private void updateVolume()
{ {
volumeTextField.setText(Formatter.formatVolume(getVolume())); volumeTextField.setText(BitSquareFormatter.formatVolume(getVolume()));
} }
private double getVolume() private double getVolume()
{ {
double amountAsDouble = Converter.stringToDouble(amountTextField.getText()); double amountAsDouble = BitSquareConverter.stringToDouble2(amountTextField.getText());
double priceAsDouble = Converter.stringToDouble(priceTextField.getText()); double priceAsDouble = BitSquareConverter.stringToDouble2(priceTextField.getText());
return amountAsDouble * priceAsDouble; return amountAsDouble * priceAsDouble;
} }
@ -272,10 +281,10 @@ public class CreateOfferController implements Initializable, ChildController
private boolean inputValid() private boolean inputValid()
{ {
double priceAsDouble = Converter.stringToDouble(priceTextField.getText()); double priceAsDouble = BitSquareConverter.stringToDouble2(priceTextField.getText());
double minAmountAsDouble = Converter.stringToDouble(minAmountTextField.getText()); double minAmountAsDouble = BitSquareConverter.stringToDouble2(minAmountTextField.getText());
double amountAsDouble = Converter.stringToDouble(amountTextField.getText()); double amountAsDouble = BitSquareConverter.stringToDouble2(amountTextField.getText());
double collateralAsDouble = Converter.stringToDouble(collateralTextField.getText()); double collateralAsDouble = BitSquareConverter.stringToDouble2(collateralTextField.getText());
return priceAsDouble > 0 && return priceAsDouble > 0 &&
amountAsDouble > 0 && amountAsDouble > 0 &&

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
@ -64,12 +65,12 @@
<Label fx:id="txTitleLabel" text="Transaction ID:" visible="false" GridPane.rowIndex="12"/> <Label fx:id="txTitleLabel" text="Transaction ID:" visible="false" GridPane.rowIndex="12"/>
<TextField fx:id="txTextField" visible="false" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="12"/> <TextField fx:id="txTextField" visible="false" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="12"/>
<ProgressIndicator fx:id="progressIndicator" id="confidence-progress-indicator" visible="false" progress="0" GridPane.columnIndex="2" GridPane.halignment="LEFT" <ConfidenceProgressIndicator fx:id="progressIndicator" visible="false" progress="0" GridPane.columnIndex="2" GridPane.halignment="LEFT"
GridPane.rowIndex="12" GridPane.rowSpan="2" GridPane.valignment="TOP"> GridPane.rowIndex="12" GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin> <GridPane.margin>
<Insets top="2.0"/> <Insets top="2.0"/>
</GridPane.margin> </GridPane.margin>
</ProgressIndicator> </ConfidenceProgressIndicator>
<Label fx:id="confirmationLabel" text="Checking confirmations..." visible="false" GridPane.columnIndex="3" GridPane.rowIndex="12"/> <Label fx:id="confirmationLabel" text="Checking confirmations..." visible="false" GridPane.columnIndex="3" GridPane.rowIndex="12"/>

View file

@ -1,22 +1,31 @@
package io.bitsquare.gui.market.orderbook; package io.bitsquare.gui.market.orderbook;
import com.google.bitcoin.core.InsufficientMoneyException;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bitsquare.bank.BankAccountType; import io.bitsquare.bank.BankAccountTypeInfo;
import io.bitsquare.btc.BtcFormatter; import io.bitsquare.btc.BtcFormatter;
import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.MainController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.market.createOffer.CreateOfferController; import io.bitsquare.gui.market.createOffer.CreateOfferController;
import io.bitsquare.gui.market.trade.TakerTradeController; import io.bitsquare.gui.market.trade.TakerTradeController;
import io.bitsquare.gui.util.Converter; import io.bitsquare.gui.util.BitSquareConverter;
import io.bitsquare.gui.util.Formatter; import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.gui.util.Icons; import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation; import io.bitsquare.gui.util.Popups;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage;
import io.bitsquare.trade.Direction; import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer; import io.bitsquare.trade.Offer;
import io.bitsquare.trade.orderbook.OrderBook; import io.bitsquare.trade.orderbook.OrderBook;
import io.bitsquare.trade.orderbook.OrderBookFilter; import io.bitsquare.trade.orderbook.OrderBookFilter;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.DSAKeyUtil;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
@ -32,6 +41,8 @@ import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.util.Callback; import javafx.util.Callback;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialogs;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -40,6 +51,8 @@ import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.ParseException; import java.text.ParseException;
import java.util.Arrays;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@ -53,6 +66,9 @@ public class OrderBookController implements Initializable, ChildController
private final OrderBookFilter orderBookFilter; private final OrderBookFilter orderBookFilter;
private User user; private User user;
private MessageFacade messageFacade; private MessageFacade messageFacade;
private WalletFacade walletFacade;
private Settings settings;
private Storage storage;
private AnimationTimer pollingTimer; private AnimationTimer pollingTimer;
private Image buyIcon = Icons.getIconImage(Icons.BUY); private Image buyIcon = Icons.getIconImage(Icons.BUY);
@ -79,12 +95,15 @@ public class OrderBookController implements Initializable, ChildController
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public OrderBookController(OrderBook orderBook, OrderBookFilter orderBookFilter, User user, MessageFacade messageFacade) public OrderBookController(OrderBook orderBook, OrderBookFilter orderBookFilter, User user, MessageFacade messageFacade, WalletFacade walletFacade, Settings settings, Storage storage)
{ {
this.orderBook = orderBook; this.orderBook = orderBook;
this.orderBookFilter = orderBookFilter; this.orderBookFilter = orderBookFilter;
this.user = user; this.user = user;
this.messageFacade = messageFacade; this.messageFacade = messageFacade;
this.walletFacade = walletFacade;
this.settings = settings;
this.storage = storage;
} }
@ -149,8 +168,50 @@ public class OrderBookController implements Initializable, ChildController
}); });
createOfferButton.setOnAction(e -> { createOfferButton.setOnAction(e -> {
ChildController nextController = navigationController.navigateToView(NavigationController.CREATE_OFFER, "Create offer"); if (user.getAccountID() == null)
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter); {
Dialogs.CommandLink settingsCommandLink = new Dialogs.CommandLink("Open settings", "You need to configure your settings before you can actively trade.");
Dialogs.CommandLink depositFeeCommandLink = new Dialogs.CommandLink("Deposit funds", "You need to pay the registration fee before you can actively trade. That is needed as prevention against fraud.");
Dialogs.CommandLink sendRegistrationCommandLink = new Dialogs.CommandLink("Publish registration", "When settings are configured and the fee deposit is done your registration transaction will be published to the Bitcoin \nnetwork.");
List<Dialogs.CommandLink> commandLinks = Arrays.asList(settingsCommandLink, depositFeeCommandLink, sendRegistrationCommandLink);
boolean settingsValid = settings.getAcceptedLanguageLocales().size() > 0;
settingsValid &= settings.getAcceptedCountries().size() > 0;
settingsValid &= settings.getAcceptedArbitrators().size() > 0;
settingsValid &= user.getCurrentBankAccount() != null;
boolean registrationFeeDeposited = walletFacade.getRegistrationBalance().compareTo(BigInteger.ZERO) > 0;
int selectedIndex = settingsValid ? (registrationFeeDeposited ? 2 : 1) : 0;
Action registrationMissingAction = Popups.openRegistrationMissingPopup("Registration missing", "Please follow these steps:", "You need to register before you can place an offer.", commandLinks, selectedIndex);
if (registrationMissingAction == settingsCommandLink)
{
MainController.getInstance().navigateToView(NavigationController.SETTINGS);
}
else if (registrationMissingAction == depositFeeCommandLink)
{
MainController.getInstance().navigateToView(NavigationController.FUNDS);
}
else if (registrationMissingAction == sendRegistrationCommandLink)
{
try
{
walletFacade.publishRegistrationTxWithExtraData(user.getStringifiedBankAccounts());
user.setAccountID(walletFacade.getRegistrationAddress().toString());
user.setMessagePubKeyAsHex(DSAKeyUtil.getHexStringFromPublicKey(messageFacade.getPubKey()));
storage.write(user.getClass().getName(), user);
} catch (InsufficientMoneyException e1)
{
Popups.openErrorPopup("Not enough money available", "There is not enough money available. Please pay in first to your wallet.");
}
}
}
else
{
ChildController nextController = navigationController.navigateToView(NavigationController.CREATE_OFFER, "Create offer");
((CreateOfferController) nextController).setOrderBookFilter(orderBookFilter);
}
}); });
//TODO do polling until broadcast works //TODO do polling until broadcast works
@ -241,7 +302,11 @@ public class OrderBookController implements Initializable, ChildController
pollingTimer = Utilities.setInterval(1000, (AnimationTimer animationTimer) -> { pollingTimer = Utilities.setInterval(1000, (AnimationTimer animationTimer) -> {
try try
{ {
messageFacade.getDirtyFlag(user.getCurrentBankAccount().getCurrency()); if (user.getCurrentBankAccount() != null)
messageFacade.getDirtyFlag(user.getCurrentBankAccount().getCurrency());
else
messageFacade.getDirtyFlag(CurrencyUtil.getDefaultCurrency());
} catch (IOException e) } catch (IOException e)
{ {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
@ -303,12 +368,12 @@ public class OrderBookController implements Initializable, ChildController
if (offer.getDirection() == Direction.SELL) if (offer.getDirection() == Direction.SELL)
{ {
icon = buyIcon; icon = buyIcon;
title = Formatter.formatDirection(Direction.BUY, true); title = BitSquareFormatter.formatDirection(Direction.BUY, true);
} }
else else
{ {
icon = sellIcon; icon = sellIcon;
title = Formatter.formatDirection(Direction.SELL, true); title = BitSquareFormatter.formatDirection(Direction.SELL, true);
} }
button.setDefaultButton(getIndex() == 0); button.setDefaultButton(getIndex() == 0);
@ -356,16 +421,16 @@ public class OrderBookController implements Initializable, ChildController
hBox.getChildren().clear(); hBox.getChildren().clear();
if (orderBookListItem != null) if (orderBookListItem != null)
{ {
Locale countryLocale = orderBookListItem.getOffer().getBankAccountCountryLocale(); Country country = orderBookListItem.getOffer().getBankAccountCountry();
try try
{ {
hBox.getChildren().add(Icons.getIconImageView("/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png")); hBox.getChildren().add(Icons.getIconImageView("/images/countries/" + country.getCode().toLowerCase() + ".png"));
} catch (Exception e) } catch (Exception e)
{ {
log.warn("Country icon not found: " + "/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png country name: " + countryLocale.getDisplayCountry()); log.warn("Country icon not found: " + "/images/countries/" + country.getCode().toLowerCase() + ".png country name: " + country.getName());
} }
Tooltip.install(this, new Tooltip(countryLocale.getDisplayCountry())); Tooltip.install(this, new Tooltip(country.getName()));
} }
} }
}; };
@ -390,8 +455,8 @@ public class OrderBookController implements Initializable, ChildController
if (orderBookListItem != null) if (orderBookListItem != null)
{ {
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum = orderBookListItem.getOffer().getBankAccountTypeEnum(); BankAccountTypeInfo.BankAccountType bankAccountType = orderBookListItem.getOffer().getBankAccountType();
setText(Localisation.get(bankAccountTypeEnum.toString())); setText(Localisation.get(bankAccountType.toString()));
} }
else else
{ {
@ -421,7 +486,7 @@ public class OrderBookController implements Initializable, ChildController
} catch (ParseException e) } catch (ParseException e)
{ {
amount.setText(oldValue); amount.setText(oldValue);
d = Converter.stringToDouble(oldValue); d = BitSquareConverter.stringToDouble2(oldValue);
} }
} }
return d; return d;
@ -431,7 +496,7 @@ public class OrderBookController implements Initializable, ChildController
{ {
double a = textInputToNumber(amount.getText(), amount.getText()); double a = textInputToNumber(amount.getText(), amount.getText());
double p = textInputToNumber(price.getText(), price.getText()); double p = textInputToNumber(price.getText(), price.getText());
volume.setText(Formatter.formatPrice(a * p)); volume.setText(BitSquareFormatter.formatPrice(a * p));
} }
} }

View file

@ -1,7 +1,7 @@
package io.bitsquare.gui.market.orderbook; package io.bitsquare.gui.market.orderbook;
import io.bitsquare.btc.BtcFormatter; import io.bitsquare.btc.BtcFormatter;
import io.bitsquare.gui.util.Formatter; import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.trade.Offer; import io.bitsquare.trade.Offer;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
@ -25,9 +25,9 @@ public class OrderBookListItem
double amountAsBtcDouble = BtcFormatter.satoshiToBTC(offer.getAmount()); double amountAsBtcDouble = BtcFormatter.satoshiToBTC(offer.getAmount());
double minAmountAsBtcDouble = BtcFormatter.satoshiToBTC(offer.getMinAmount()); double minAmountAsBtcDouble = BtcFormatter.satoshiToBTC(offer.getMinAmount());
this.price.set(Formatter.formatPrice(offer.getPrice())); this.price.set(BitSquareFormatter.formatPrice(offer.getPrice()));
this.amount.set(Formatter.formatAmountWithMinAmount(amountAsBtcDouble, minAmountAsBtcDouble)); this.amount.set(BitSquareFormatter.formatAmountWithMinAmount(amountAsBtcDouble, minAmountAsBtcDouble));
this.volume.set(Formatter.formatVolumeWithMinVolume(offer.getVolume(), offer.getMinVolume())); this.volume.set(BitSquareFormatter.formatVolumeWithMinVolume(offer.getVolume(), offer.getMinVolume()));
} }
public Offer getOffer() public Offer getOffer()

View file

@ -9,11 +9,12 @@ import io.bitsquare.btc.Fees;
import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.components.processbar.ProcessStepBar; import io.bitsquare.gui.components.processbar.ProcessStepBar;
import io.bitsquare.gui.components.processbar.ProcessStepItem; import io.bitsquare.gui.components.processbar.ProcessStepItem;
import io.bitsquare.gui.util.Converter; import io.bitsquare.gui.util.BitSquareConverter;
import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.gui.util.FormBuilder; import io.bitsquare.gui.util.FormBuilder;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.gui.util.Popups; import io.bitsquare.gui.util.Popups;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.TradeMessage; import io.bitsquare.msg.TradeMessage;
@ -21,8 +22,8 @@ import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer; import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
import io.bitsquare.trade.Trading; import io.bitsquare.trade.Trading;
import io.bitsquare.trade.taker.TakerPaymentProtocol; import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
import io.bitsquare.trade.taker.TakerPaymentProtocolListener; import io.bitsquare.trade.payment.taker.TakerPaymentProtocolListener;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@ -167,15 +168,15 @@ public class TakerTradeController implements Initializable, ChildController
Label amountRangeLabel = new Label("(" + BtcFormatter.formatSatoshis(offer.getMinAmount(), false) + " - " + BtcFormatter.formatSatoshis(offer.getAmount(), false) + ")"); Label amountRangeLabel = new Label("(" + BtcFormatter.formatSatoshis(offer.getMinAmount(), false) + " - " + BtcFormatter.formatSatoshis(offer.getAmount(), false) + ")");
gridPane.add(amountRangeLabel, 2, row); gridPane.add(amountRangeLabel, 2, row);
FormBuilder.addTextField(gridPane, "Price (" + offer.getCurrency() + "/BTC):", Formatter.formatPrice(offer.getPrice()), ++row); FormBuilder.addTextField(gridPane, "Price (" + offer.getCurrency() + "/BTC):", BitSquareFormatter.formatPrice(offer.getPrice()), ++row);
totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row); totalLabel = FormBuilder.addTextField(gridPane, "Total (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row); collateralTextField = FormBuilder.addTextField(gridPane, "Collateral (BTC):", "", ++row);
applyCollateral(); applyCollateral();
FormBuilder.addTextField(gridPane, "Offer fee (BTC):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Fees.TX_FEE)), ++row); FormBuilder.addTextField(gridPane, "Offer fee (BTC):", Utils.bitcoinValueToFriendlyString(Fees.OFFER_TAKER_FEE.add(Fees.TX_FEE)), ++row);
totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPay(), ++row); totalToPayLabel = FormBuilder.addTextField(gridPane, "Total to pay (BTC):", getTotalToPay(), ++row);
isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row); isOnlineTextField = FormBuilder.addTextField(gridPane, "Online status:", "Checking offerers online status...", ++row);
ProgressIndicator isOnlineChecker = new ProgressIndicator(); ConfidenceProgressIndicator isOnlineChecker = new ConfidenceProgressIndicator();
isOnlineChecker.setPrefSize(20, 20); isOnlineChecker.setPrefSize(20, 20);
isOnlineChecker.setLayoutY(3); isOnlineChecker.setLayoutY(3);
isOnlineCheckerHolder = new Pane(); isOnlineCheckerHolder = new Pane();
@ -196,24 +197,24 @@ public class TakerTradeController implements Initializable, ChildController
// details // details
FormBuilder.addVSpacer(gridPane, ++row); FormBuilder.addVSpacer(gridPane, ++row);
FormBuilder.addHeaderLabel(gridPane, "Offerer details:", ++row); FormBuilder.addHeaderLabel(gridPane, "Offerer details:", ++row);
FormBuilder.addTextField(gridPane, "Bank account type:", offer.getBankAccountTypeEnum().toString(), ++row); FormBuilder.addTextField(gridPane, "Bank account type:", offer.getBankAccountType().toString(), ++row);
FormBuilder.addTextField(gridPane, "Country:", offer.getBankAccountCountryLocale().getDisplayCountry(), ++row); FormBuilder.addTextField(gridPane, "Country:", offer.getBankAccountCountry().getName(), ++row);
FormBuilder.addTextField(gridPane, "Arbitrator:", offer.getArbitrator().getName(), ++row); FormBuilder.addTextField(gridPane, "Arbitrator:", offer.getArbitrator().getName(), ++row);
Label arbitratorLink = new Label(offer.getArbitrator().getUrl()); Label arbitratorLink = new Label(offer.getArbitrator().getWebUrl());
arbitratorLink.setId("label-url"); arbitratorLink.setId("label-url");
gridPane.add(arbitratorLink, 2, row); gridPane.add(arbitratorLink, 2, row);
arbitratorLink.setOnMouseClicked(e -> { arbitratorLink.setOnMouseClicked(e -> {
try try
{ {
Utilities.openURL(offer.getArbitrator().getUrl()); Utilities.openURL(offer.getArbitrator().getWebUrl());
} catch (Exception e1) } catch (Exception e1)
{ {
log.warn(e1.toString()); log.warn(e1.toString());
} }
}); });
FormBuilder.addTextField(gridPane, "Supported languages:", Formatter.languageLocalesToString(offer.getAcceptedLanguageLocales()), ++row); FormBuilder.addTextField(gridPane, "Supported languages:", BitSquareFormatter.languageLocalesToString(offer.getAcceptedLanguageLocales()), ++row);
FormBuilder.addTextField(gridPane, "Supported countries:", Formatter.countryLocalesToString(offer.getAcceptedCountryLocales()), ++row); FormBuilder.addTextField(gridPane, "Supported countries:", BitSquareFormatter.countryLocalesToString(offer.getAcceptedCountries()), ++row);
} }
private void takeOffer() private void takeOffer()
@ -253,7 +254,7 @@ public class TakerTradeController implements Initializable, ChildController
gridPane.add(progressBar, 1, row); gridPane.add(progressBar, 1, row);
FormBuilder.addLabel(gridPane, "Status:", "", ++row); FormBuilder.addLabel(gridPane, "Status:", "", ++row);
ProgressIndicator progressIndicator = new ProgressIndicator(); ConfidenceProgressIndicator progressIndicator = new ConfidenceProgressIndicator();
progressIndicator.setPrefSize(20, 20); progressIndicator.setPrefSize(20, 20);
progressIndicator.setLayoutY(2); progressIndicator.setLayoutY(2);
Pane progressIndicatorHolder = new Pane(); Pane progressIndicatorHolder = new Pane();
@ -362,7 +363,7 @@ public class TakerTradeController implements Initializable, ChildController
row = -1; row = -1;
FormBuilder.addHeaderLabel(gridPane, "Trade successfully completed", ++row); FormBuilder.addHeaderLabel(gridPane, "Trade successfully completed", ++row);
String fiatReceived = Formatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount())); String fiatReceived = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
FormBuilder.addTextField(gridPane, "You have sold (BTC):", Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()), ++row); FormBuilder.addTextField(gridPane, "You have sold (BTC):", Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()), ++row);
if (takerIsSelling()) if (takerIsSelling())
@ -375,7 +376,7 @@ public class TakerTradeController implements Initializable, ChildController
{ {
//TODO //TODO
FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false), ++row); FormBuilder.addTextField(gridPane, "You got returned collateral (BTC):", BtcFormatter.formatSatoshis(getCollateralInSatoshis(), false), ++row);
FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", Formatter.formatVolume(getVolume()), ++row); FormBuilder.addTextField(gridPane, "You have received (" + offer.getCurrency() + "):", BitSquareFormatter.formatVolume(getVolume()), ++row);
FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.formatSatoshis(offer.getAmount(), false), ++row); FormBuilder.addTextField(gridPane, "You have received (BTC):", BtcFormatter.formatSatoshis(offer.getAmount(), false), ++row);
} }
@ -426,12 +427,12 @@ public class TakerTradeController implements Initializable, ChildController
private void applyVolume() private void applyVolume()
{ {
totalLabel.setText(Formatter.formatVolume(getVolume(), offer.getCurrency())); totalLabel.setText(BitSquareFormatter.formatVolume(getVolume(), offer.getCurrency()));
} }
private double getVolume() private double getVolume()
{ {
return offer.getPrice() * Converter.stringToDouble(amountTextField.getText()); return offer.getPrice() * BitSquareConverter.stringToDouble2(amountTextField.getText());
} }
private String getTotalToPay() private String getTotalToPay()
@ -443,7 +444,7 @@ public class TakerTradeController implements Initializable, ChildController
else else
{ {
return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE).add(getCollateralInSatoshis()), false) + "\n" + return BtcFormatter.formatSatoshis(Fees.OFFER_TAKER_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(Fees.TX_FEE).add(getCollateralInSatoshis()), false) + "\n" +
Formatter.formatVolume(getVolume(), offer.getCurrency()); BitSquareFormatter.formatVolume(getVolume(), offer.getCurrency());
} }
} }
@ -455,7 +456,7 @@ public class TakerTradeController implements Initializable, ChildController
private BigInteger getCollateralInSatoshis() private BigInteger getCollateralInSatoshis()
{ {
double amount = Converter.stringToDouble(amountTextField.getText()); double amount = BitSquareConverter.stringToDouble2(amountTextField.getText());
double resultDouble = amount * (double) offer.getCollateral() / 100.0; double resultDouble = amount * (double) offer.getCollateral() / 100.0;
BigInteger result = BtcFormatter.doubleValueToSatoshis(resultDouble); BigInteger result = BtcFormatter.doubleValueToSatoshis(resultDouble);
return result; return result;

View file

@ -6,16 +6,18 @@ import com.google.inject.Inject;
import de.jensd.fx.fontawesome.AwesomeDude; import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.fontawesome.AwesomeIcon;
import io.bitsquare.bank.BankAccount; import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType; import io.bitsquare.bank.BankAccountTypeInfo;
import io.bitsquare.btc.BtcFormatter; import io.bitsquare.btc.BtcFormatter;
import io.bitsquare.btc.Fees; import io.bitsquare.btc.Fees;
import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.BitSquareFormatter;
import io.bitsquare.gui.util.ConfidenceDisplay; import io.bitsquare.gui.util.ConfidenceDisplay;
import io.bitsquare.gui.util.Formatter;
import io.bitsquare.gui.util.Icons; import io.bitsquare.gui.util.Icons;
import io.bitsquare.gui.util.Localisation; import io.bitsquare.locale.Country;
import io.bitsquare.locale.Localisation;
import io.bitsquare.trade.Direction; import io.bitsquare.trade.Direction;
import io.bitsquare.trade.Offer; import io.bitsquare.trade.Offer;
import io.bitsquare.trade.Trade; import io.bitsquare.trade.Trade;
@ -65,7 +67,7 @@ public class OrdersController implements Initializable, ChildController
@FXML @FXML
private TableColumn<String, TradesTableItem> directionColumn, countryColumn, bankAccountTypeColumn, priceColumn, amountColumn, volumeColumn, statusColumn, selectColumn; private TableColumn<String, TradesTableItem> directionColumn, countryColumn, bankAccountTypeColumn, priceColumn, amountColumn, volumeColumn, statusColumn, selectColumn;
@FXML @FXML
private ProgressIndicator progressIndicator; private ConfidenceProgressIndicator progressIndicator;
@FXML @FXML
private Label txTitleLabel, txHeaderLabel, confirmationLabel, txIDCopyIcon, holderNameCopyIcon, primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon, bankAccountDetailsHeaderLabel, private Label txTitleLabel, txHeaderLabel, confirmationLabel, txIDCopyIcon, holderNameCopyIcon, primaryBankAccountIDCopyIcon, secondaryBankAccountIDCopyIcon, bankAccountDetailsHeaderLabel,
bankAccountTypeTitleLabel, holderNameTitleLabel, primaryBankAccountIDTitleLabel, secondaryBankAccountIDTitleLabel; bankAccountTypeTitleLabel, holderNameTitleLabel, primaryBankAccountIDTitleLabel, secondaryBankAccountIDTitleLabel;
@ -309,7 +311,7 @@ public class OrdersController implements Initializable, ChildController
primaryBankAccountIDTitleLabel.setText("Total fees (offer fee + tx fee):"); primaryBankAccountIDTitleLabel.setText("Total fees (offer fee + tx fee):");
secondaryBankAccountIDTitleLabel.setText("Refunded collateral:"); secondaryBankAccountIDTitleLabel.setText("Refunded collateral:");
String fiatPayed = Formatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount())); String fiatPayed = BitSquareFormatter.formatVolume(trade.getOffer().getPrice() * BtcFormatter.satoshiToBTC(trade.getTradeAmount()));
bankAccountTypeTextField.setText(Utils.bitcoinValueToFriendlyString(trade.getTradeAmount())); bankAccountTypeTextField.setText(Utils.bitcoinValueToFriendlyString(trade.getTradeAmount()));
holderNameTextField.setText(fiatPayed); holderNameTextField.setText(fiatPayed);
@ -327,7 +329,7 @@ public class OrdersController implements Initializable, ChildController
private void setBankData(Trade trade) private void setBankData(Trade trade)
{ {
BankAccount bankAccount = trade.getContract().getTakerBankAccount(); BankAccount bankAccount = trade.getContract().getTakerBankAccount();
bankAccountTypeTextField.setText(bankAccount.getBankAccountType().getType().toString()); bankAccountTypeTextField.setText(bankAccount.getBankAccountTypeInfo().getType().toString());
holderNameTextField.setText(bankAccount.getAccountHolderName()); holderNameTextField.setText(bankAccount.getAccountHolderName());
primaryBankAccountIDTextField.setText(bankAccount.getAccountPrimaryID()); primaryBankAccountIDTextField.setText(bankAccount.getAccountPrimaryID());
secondaryBankAccountIDTextField.setText(bankAccount.getAccountSecondaryID()); secondaryBankAccountIDTextField.setText(bankAccount.getAccountSecondaryID());
@ -399,16 +401,16 @@ public class OrdersController implements Initializable, ChildController
hBox.getChildren().clear(); hBox.getChildren().clear();
if (tradesTableItem != null) if (tradesTableItem != null)
{ {
Locale countryLocale = tradesTableItem.getTrade().getOffer().getBankAccountCountryLocale(); Country country = tradesTableItem.getTrade().getOffer().getBankAccountCountry();
try try
{ {
hBox.getChildren().add(Icons.getIconImageView("/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png")); hBox.getChildren().add(Icons.getIconImageView("/images/countries/" + country.getCode().toLowerCase() + ".png"));
} catch (Exception e) } catch (Exception e)
{ {
log.warn("Country icon not found: " + "/images/countries/" + countryLocale.getCountry().toLowerCase() + ".png country name: " + countryLocale.getDisplayCountry()); log.warn("Country icon not found: " + "/images/countries/" + country.getCode().toLowerCase() + ".png country name: " + country.getName());
} }
Tooltip.install(this, new Tooltip(countryLocale.getDisplayCountry())); Tooltip.install(this, new Tooltip(country.getName()));
} }
} }
}; };
@ -433,8 +435,8 @@ public class OrdersController implements Initializable, ChildController
if (tradesTableItem != null) if (tradesTableItem != null)
{ {
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum = tradesTableItem.getTrade().getOffer().getBankAccountTypeEnum(); BankAccountTypeInfo.BankAccountType bankAccountType = tradesTableItem.getTrade().getOffer().getBankAccountType();
setText(Localisation.get(bankAccountTypeEnum.toString())); setText(Localisation.get(bankAccountType.toString()));
} }
else else
{ {
@ -478,12 +480,12 @@ public class OrdersController implements Initializable, ChildController
if (offer.getDirection() == Direction.SELL) if (offer.getDirection() == Direction.SELL)
{ {
icon = buyIcon; icon = buyIcon;
title = io.bitsquare.gui.util.Formatter.formatDirection(Direction.BUY, true); title = BitSquareFormatter.formatDirection(Direction.BUY, true);
} }
else else
{ {
icon = sellIcon; icon = sellIcon;
title = io.bitsquare.gui.util.Formatter.formatDirection(Direction.SELL, true); title = BitSquareFormatter.formatDirection(Direction.SELL, true);
} }
button.setDisable(true); button.setDisable(true);
iconView.setImage(icon); iconView.setImage(icon);

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator?>
<?import javafx.geometry.*?> <?import javafx.geometry.*?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.PropertyValueFactory?> <?import javafx.scene.control.cell.PropertyValueFactory?>
@ -71,12 +72,12 @@
<Tooltip text="Copy address to clipboard"/> <Tooltip text="Copy address to clipboard"/>
</tooltip> </tooltip>
</Label> </Label>
<ProgressIndicator fx:id="progressIndicator" id="confidence-progress-indicator" visible="false" progress="0" GridPane.columnIndex="3" GridPane.halignment="LEFT" GridPane.rowIndex="1" <ConfidenceProgressIndicator fx:id="progressIndicator" visible="false" progress="0" GridPane.columnIndex="3" GridPane.halignment="LEFT" GridPane.rowIndex="1"
GridPane.rowSpan="2" GridPane.valignment="TOP"> GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin> <GridPane.margin>
<Insets top="2.0"/> <Insets top="2.0"/>
</GridPane.margin> </GridPane.margin>
</ProgressIndicator> </ConfidenceProgressIndicator>
<Label fx:id="confirmationLabel" visible="false" GridPane.columnIndex="4" GridPane.rowIndex="1"/> <Label fx:id="confirmationLabel" visible="false" GridPane.columnIndex="4" GridPane.rowIndex="1"/>
<!-- row 2 --> <!-- row 2 -->

View file

@ -1,23 +1,83 @@
package io.bitsquare.gui.settings; package io.bitsquare.gui.settings;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bitsquare.BitSquare;
import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountTypeInfo;
import io.bitsquare.di.GuiceFXMLLoader;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.util.BitSquareValidator;
import io.bitsquare.gui.util.Icons;
import io.bitsquare.locale.*;
import io.bitsquare.settings.Settings; import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage; import io.bitsquare.storage.Storage;
import io.bitsquare.user.Arbitrator;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable; import javafx.fxml.Initializable;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Callback;
import javafx.util.StringConverter;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ResourceBundle; import java.util.*;
public class SettingsController implements Initializable, ChildController public class SettingsController implements Initializable, ChildController, NavigationController
{ {
private User user; private User user;
private Settings settings; private Settings settings;
private Storage storage; private Storage storage;
private NavigationController navigationController; private NavigationController navigationController;
private ChildController childController;
private ObservableList<Locale> languageList;
private ObservableList<Country> countryList;
private List<String> regionList;
private ObservableList<Arbitrator> arbitratorList;
private Region selectedRegion, selectedBankAccountRegion;
@FXML
private ListView<Locale> languagesListView;
@FXML
private ListView<Country> countriesListView;
@FXML
private ListView<Arbitrator> arbitratorsListView;
@FXML
private ComboBox<Locale> languageComboBox;
@FXML
private ComboBox<Region> regionComboBox, bankAccountRegionComboBox;
@FXML
private ComboBox<Country> countryComboBox, bankAccountCountryComboBox;
@FXML
private TextField bankAccountTitleTextField, bankAccountHolderNameTextField, bankAccountPrimaryIDTextField, bankAccountSecondaryIDTextField;
@FXML
private Button saveBankAccountButton, addBankAccountButton;
@FXML
private ComboBox<BankAccount> bankAccountComboBox;
@FXML
private ComboBox<BankAccountTypeInfo> bankAccountTypesComboBox;
@FXML
private ComboBox<Currency> bankAccountCurrencyComboBox;
///////////////////////////////////////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public SettingsController(User user, Settings settings, Storage storage) public SettingsController(User user, Settings settings, Storage storage)
@ -25,14 +85,55 @@ public class SettingsController implements Initializable, ChildController
this.user = user; this.user = user;
this.settings = settings; this.settings = settings;
this.storage = storage; this.storage = storage;
Settings savedSettings = (Settings) storage.read(settings.getClass().getName());
if (savedSettings != null)
{
settings.updateFromStorage(savedSettings);
languageList = FXCollections.observableArrayList(settings.getAcceptedLanguageLocales());
countryList = FXCollections.observableArrayList(settings.getAcceptedCountries());
arbitratorList = FXCollections.observableArrayList(settings.getAcceptedArbitrators());
}
else
{
languageList = FXCollections.observableArrayList(new ArrayList<>());
countryList = FXCollections.observableArrayList(new ArrayList<>());
arbitratorList = FXCollections.observableArrayList(new ArrayList<>());
addLanguage(LanguageUtil.getDefaultLanguageLocale());
addCountry(CountryUtil.getDefaultCountry());
}
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Public Methods
///////////////////////////////////////////////////////////////////////////////////////////
public void updateArbitrators()
{
arbitratorList = FXCollections.observableArrayList(settings.getAcceptedArbitrators());
initArbitrators();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: Initializable
///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
public void initialize(URL url, ResourceBundle rb) public void initialize(URL url, ResourceBundle rb)
{ {
setupGeneralSettingsScreen();
initBankAccountScreen();
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: ChildController
///////////////////////////////////////////////////////////////////////////////////////////
@Override @Override
public void setNavigationController(NavigationController navigationController) public void setNavigationController(NavigationController navigationController)
{ {
@ -45,5 +146,661 @@ public class SettingsController implements Initializable, ChildController
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Interface implementation: NavigationController
///////////////////////////////////////////////////////////////////////////////////////////
@Override
public ChildController navigateToView(String fxmlView)
{
return navigateToView(fxmlView, "");
}
@Override
public ChildController navigateToView(String fxmlView, String title)
{
if (childController != null)
childController.cleanup();
final GuiceFXMLLoader loader = new GuiceFXMLLoader(getClass().getResource(fxmlView), Localisation.getResourceBundle());
try
{
final Node view = loader.load();
childController = loader.getController();
childController.setNavigationController(this);
final Stage rootStage = BitSquare.getStage();
final Stage stage = new Stage();
stage.setTitle(title);
stage.setMinWidth(800);
stage.setMinHeight(500);
stage.setWidth(800);
stage.setHeight(600);
stage.setX(rootStage.getX() + 50);
stage.setY(rootStage.getY() + 50);
stage.initModality(Modality.WINDOW_MODAL);
stage.initOwner(rootStage);
Scene scene = new Scene((Parent) view, 800, 600);
stage.setScene(scene);
stage.setOnHidden(new EventHandler<WindowEvent>()
{
@Override
public void handle(WindowEvent windowEvent)
{
if (fxmlView.equals(NavigationController.ARBITRATOR_OVERVIEW))
updateArbitrators();
}
});
stage.show();
return childController;
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI handlers
///////////////////////////////////////////////////////////////////////////////////////////
// General Settings
@FXML
public void onAddLanguage(ActionEvent actionEvent)
{
addLanguage(languageComboBox.getSelectionModel().getSelectedItem());
languageComboBox.getSelectionModel().clearSelection();
}
@FXML
public void onSelectRegion(ActionEvent actionEvent)
{
countryComboBox.setVisible(true);
selectedRegion = regionComboBox.getSelectionModel().getSelectedItem();
countryComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedRegion)));
}
@FXML
public void onAddCountry(ActionEvent actionEvent)
{
addCountry(countryComboBox.getSelectionModel().getSelectedItem());
countryComboBox.getSelectionModel().clearSelection();
}
@FXML
public void onAddArbitrator(ActionEvent actionEvent)
{
navigateToView(NavigationController.ARBITRATOR_OVERVIEW, "Arbitration selection");
}
// Bank Account Settings
@FXML
public void selectBankAccount(ActionEvent actionEvent)
{
BankAccount bankAccount = bankAccountComboBox.getSelectionModel().getSelectedItem();
if (bankAccount != null && bankAccount != user.getCurrentBankAccount())
{
user.setCurrentBankAccount(bankAccount);
storage.write(user.getClass().getName(), user);
initBankAccountScreen();
}
}
@FXML
public void selectBankAccountType(ActionEvent actionEvent)
{
BankAccountTypeInfo bankAccountTypeInfo = bankAccountTypesComboBox.getSelectionModel().getSelectedItem();
if (bankAccountTypeInfo != null)
{
bankAccountTitleTextField.setText("");
bankAccountPrimaryIDTextField.setText("");
bankAccountPrimaryIDTextField.setPromptText(bankAccountTypeInfo.getPrimaryIDName());
bankAccountSecondaryIDTextField.setText("");
bankAccountSecondaryIDTextField.setPromptText(bankAccountTypeInfo.getSecondaryIDName());
}
}
@FXML
public void onSelectBankAccountRegion(ActionEvent actionEvent)
{
bankAccountCountryComboBox.setVisible(true);
selectedBankAccountRegion = bankAccountRegionComboBox.getSelectionModel().getSelectedItem();
bankAccountCountryComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllCountriesFor(selectedBankAccountRegion)));
}
@FXML
public void onAddBankAccount(ActionEvent actionEvent)
{
resetBankAccountInput();
}
@FXML
public void onRemoveBankAccount(ActionEvent actionEvent)
{
removeBankAccount();
}
@FXML
public void onSaveBankAccount(ActionEvent actionEvent)
{
saveBankAccount();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Private methods
///////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////
// General Settings
///////////////////////////////////////////////////////////////////////////////////////////
private void setupGeneralSettingsScreen()
{
initLanguage();
initCountry();
initArbitrators();
}
private void initLanguage()
{
languagesListView.setCellFactory(new Callback<ListView<Locale>, ListCell<Locale>>()
{
@Override
public ListCell<Locale> call(ListView<Locale> list)
{
return new ListCell<Locale>()
{
final HBox hBox = new HBox();
final Label label = new Label();
final Button removeButton = new Button();
final ImageView icon = Icons.getIconImageView(Icons.REMOVE);
{
label.setPrefWidth(565);
icon.setMouseTransparent(true);
removeButton.setGraphic(icon);
removeButton.setId("icon-button");
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(label, removeButton);
}
@Override
public void updateItem(final Locale item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
label.setText(item.getDisplayName());
removeButton.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent actionEvent)
{
removeLanguage(item);
}
});
setGraphic(hBox);
}
else
{
setGraphic(null);
}
}
};
}
}
);
languagesListView.setItems(languageList);
languageComboBox.setItems(FXCollections.observableArrayList(LanguageUtil.getAllLanguageLocales()));
languageComboBox.setConverter(new StringConverter<Locale>()
{
@Override
public String toString(Locale locale)
{
return locale.getDisplayLanguage();
}
@Override
public Locale fromString(String s)
{
return null;
}
});
}
private void initCountry()
{
regionComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllRegions()));
regionComboBox.setConverter(new StringConverter<Region>()
{
@Override
public String toString(Region region)
{
return region.getName();
}
@Override
public Region fromString(String s)
{
return null;
}
});
countriesListView.setCellFactory(new Callback<ListView<Country>, ListCell<Country>>()
{
@Override
public ListCell<Country> call(ListView<Country> list)
{
return new ListCell<Country>()
{
final HBox hBox = new HBox();
final Label label = new Label();
final Button removeButton = new Button();
final ImageView icon = Icons.getIconImageView(Icons.REMOVE);
{
label.setPrefWidth(565);
icon.setMouseTransparent(true);
removeButton.setGraphic(icon);
removeButton.setId("icon-button");
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(label, removeButton);
}
@Override
public void updateItem(final Country item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
label.setText(item.getName());
removeButton.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent actionEvent)
{
removeCountry(item);
}
});
setGraphic(hBox);
}
else
{
setGraphic(null);
}
}
};
}
}
);
countriesListView.setItems(countryList);
countryComboBox.setConverter(new StringConverter<Country>()
{
@Override
public String toString(Country country)
{
return country.getName();
}
@Override
public Country fromString(String s)
{
return null;
}
});
}
private void initArbitrators()
{
arbitratorsListView.setCellFactory(new Callback<ListView<Arbitrator>, ListCell<Arbitrator>>()
{
@Override
public ListCell<Arbitrator> call(ListView<Arbitrator> list)
{
return new ListCell<Arbitrator>()
{
final HBox hBox = new HBox();
final Label label = new Label();
final Button removeButton = new Button();
final ImageView icon = Icons.getIconImageView(Icons.REMOVE);
{
label.setPrefWidth(565);
icon.setMouseTransparent(true);
removeButton.setGraphic(icon);
removeButton.setId("icon-button");
hBox.setSpacing(3);
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.getChildren().addAll(label, removeButton);
}
@Override
public void updateItem(final Arbitrator item, boolean empty)
{
super.updateItem(item, empty);
if (item != null)
{
label.setText(item.getName());
removeButton.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent actionEvent)
{
removeArbitrator(item);
}
});
setGraphic(hBox);
}
else
{
setGraphic(null);
}
}
};
}
}
);
arbitratorsListView.setItems(arbitratorList);
}
private void addLanguage(Locale item)
{
if (!languageList.contains(item) && item != null)
{
languageList.add(item);
settings.addAcceptedLanguageLocale(item);
storage.write(settings.getClass().getName(), settings);
}
}
private void removeLanguage(Locale item)
{
languageList.remove(item);
settings.removeAcceptedLanguageLocale(item);
storage.write(settings.getClass().getName(), settings);
}
private void addCountry(Country item)
{
if (!countryList.contains(item) && item != null)
{
countryList.add(item);
settings.addAcceptedCountry(item);
storage.write(settings.getClass().getName(), settings);
}
}
private void removeCountry(Country item)
{
countryList.remove(item);
settings.removeAcceptedCountry(item);
storage.write(settings.getClass().getName(), settings);
}
private void removeArbitrator(Arbitrator item)
{
arbitratorList.remove(item);
settings.removeAcceptedArbitrator(item);
storage.write(settings.getClass().getName(), settings);
}
///////////////////////////////////////////////////////////////////////////////////////////
// Bank Account Settings
///////////////////////////////////////////////////////////////////////////////////////////
private void initBankAccountScreen()
{
initBankAccountComboBox();
initBankAccountTypesComboBox();
initBankAccountCurrencyComboBox();
initBankAccountCountryComboBox();
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null)
{
bankAccountTitleTextField.setText(currentBankAccount.getAccountTitle());
bankAccountHolderNameTextField.setText(currentBankAccount.getAccountHolderName());
bankAccountPrimaryIDTextField.setText(currentBankAccount.getAccountPrimaryID());
bankAccountPrimaryIDTextField.setPromptText(currentBankAccount.getBankAccountTypeInfo().getPrimaryIDName());
bankAccountSecondaryIDTextField.setText(currentBankAccount.getAccountSecondaryID());
bankAccountSecondaryIDTextField.setPromptText(currentBankAccount.getBankAccountTypeInfo().getSecondaryIDName());
}
else
{
resetBankAccountInput();
}
}
private void resetBankAccountInput()
{
bankAccountTitleTextField.setText("");
bankAccountHolderNameTextField.setText("");
bankAccountPrimaryIDTextField.setText("");
bankAccountPrimaryIDTextField.setPromptText("");
bankAccountSecondaryIDTextField.setText("");
bankAccountSecondaryIDTextField.setPromptText("");
bankAccountTypesComboBox.getSelectionModel().clearSelection();
bankAccountCurrencyComboBox.getSelectionModel().clearSelection();
}
private void initBankAccountComboBox()
{
if (user.getBankAccounts().size() > 0)
{
bankAccountComboBox.setPromptText("Select bank account");
bankAccountComboBox.setDisable(false);
bankAccountComboBox.setItems(FXCollections.observableArrayList(user.getBankAccounts()));
bankAccountComboBox.setConverter(new StringConverter<BankAccount>()
{
@Override
public String toString(BankAccount bankAccount)
{
return bankAccount.getAccountTitle();
}
@Override
public BankAccount fromString(String s)
{
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null)
{
int index = bankAccountComboBox.getItems().indexOf(currentBankAccount);
bankAccountComboBox.getSelectionModel().select(index);
}
}
else
{
bankAccountComboBox.setPromptText("No bank account available");
bankAccountComboBox.setDisable(true);
}
}
private void initBankAccountTypesComboBox()
{
bankAccountTypesComboBox.setItems(FXCollections.observableArrayList(BankAccountTypeInfo.getAllBankAccountTypeInfoObjects()));
bankAccountTypesComboBox.setConverter(new StringConverter<BankAccountTypeInfo>()
{
@Override
public String toString(BankAccountTypeInfo bankAccountTypeInfo)
{
return Localisation.get(bankAccountTypeInfo.getType().toString());
}
@Override
public BankAccountTypeInfo fromString(String s)
{
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null)
{
int index = bankAccountTypesComboBox.getItems().indexOf(currentBankAccount.getBankAccountTypeInfo());
bankAccountTypesComboBox.getSelectionModel().select(index);
}
}
private void initBankAccountCurrencyComboBox()
{
bankAccountCurrencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getAllCurrencies()));
bankAccountCurrencyComboBox.setConverter(new StringConverter<Currency>()
{
@Override
public String toString(Currency currency)
{
return currency.getCurrencyCode() + " (" + currency.getDisplayName() + ")";
}
@Override
public Currency fromString(String s)
{
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null)
{
Currency currentCurrency = currentBankAccount.getCurrency();
int index = bankAccountCurrencyComboBox.getItems().indexOf(currentCurrency);
bankAccountCurrencyComboBox.getSelectionModel().select(index);
}
}
private void initBankAccountCountryComboBox()
{
bankAccountRegionComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllRegions()));
bankAccountRegionComboBox.setConverter(new StringConverter<Region>()
{
@Override
public String toString(Region region)
{
return region.getName();
}
@Override
public Region fromString(String s)
{
return null;
}
});
bankAccountCountryComboBox.setConverter(new StringConverter<Country>()
{
@Override
public String toString(Country country)
{
return country.getName();
}
@Override
public Country fromString(String s)
{
return null;
}
});
BankAccount currentBankAccount = user.getCurrentBankAccount();
if (currentBankAccount != null)
{
Country currentCountry = currentBankAccount.getCountry();
Region currentRegion = currentCountry.getRegion();
int regionIndex = bankAccountRegionComboBox.getItems().indexOf(currentRegion);
bankAccountRegionComboBox.getSelectionModel().select(regionIndex);
bankAccountCountryComboBox.setVisible(true);
int countryIndex = bankAccountCountryComboBox.getItems().indexOf(currentCountry);
bankAccountCountryComboBox.getSelectionModel().select(countryIndex);
}
}
private void saveBankAccount()
{
if (verifyBankAccountData())
{
BankAccount bankAccount = new BankAccount(
bankAccountTypesComboBox.getSelectionModel().getSelectedItem(),
bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem(),
bankAccountCountryComboBox.getSelectionModel().getSelectedItem(),
bankAccountTitleTextField.getText(),
bankAccountHolderNameTextField.getText(),
bankAccountPrimaryIDTextField.getText(),
bankAccountSecondaryIDTextField.getText());
user.addBankAccount(bankAccount);
storage.write(user.getClass().getName(), user);
initBankAccountScreen();
}
}
private void removeBankAccount()
{
user.removeCurrentBankAccount();
storage.write(user.getClass().getName(), user);
initBankAccountScreen();
}
private boolean verifyBankAccountData()
{
try
{
TextField[] textFields = {bankAccountTitleTextField, bankAccountHolderNameTextField, bankAccountPrimaryIDTextField, bankAccountSecondaryIDTextField};
BitSquareValidator.resetTextFields(textFields);
BitSquareValidator.textFieldsNotEmpty(textFields);
BankAccountTypeInfo bankAccountTypeInfo = bankAccountTypesComboBox.getSelectionModel().getSelectedItem();
BitSquareValidator.textFieldBankAccountPrimaryIDIsValid(bankAccountPrimaryIDTextField, bankAccountTypeInfo);
BitSquareValidator.textFieldBankAccountSecondaryIDIsValid(bankAccountSecondaryIDTextField, bankAccountTypeInfo);
return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null
&& bankAccountCountryComboBox.getSelectionModel().getSelectedItem() != null
&& bankAccountCurrencyComboBox.getSelectionModel().getSelectedItem() != null;
} catch (BitSquareValidator.ValidationException e)
{
return false;
}
}
} }

View file

@ -1,14 +1,112 @@
<?import javafx.scene.control.Label?> <?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<AnchorPane fx:controller="io.bitsquare.gui.settings.SettingsController" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="10.0" AnchorPane.rightAnchor="10.0" AnchorPane.topAnchor="10.0" <?import javafx.geometry.Insets?>
xmlns:fx="http://javafx.com/fxml"> <?import javafx.scene.control.*?>
<children> <?import javafx.scene.layout.*?>
<VBox spacing="20" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <AnchorPane prefHeight="600.0" prefWidth="800.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
<children> xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="io.bitsquare.gui.settings.SettingsController">
<Label id="headline-label" text="Settings"/> <TabPane fx:id="tabPane" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
</children> <Tab text="General" closable="false">
</VBox> <GridPane hgap="5.0" vgap="5.0">
</children> <padding>
</AnchorPane> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<children>
<Label text="Accepted languages:"/>
<ListView fx:id="languagesListView" prefHeight="300.0" prefWidth="400.0" GridPane.columnIndex="1"/>
<Label text="Accepted countries:" GridPane.rowIndex="2"/>
<Label text="Accepted arbitrators:" GridPane.rowIndex="4"/>
<ListView fx:id="countriesListView" prefHeight="300.0" prefWidth="400.0" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<ListView fx:id="arbitratorsListView" prefHeight="300.0" prefWidth="400.0" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<ComboBox fx:id="languageComboBox" onAction="#onAddLanguage" prefWidth="150.0" promptText="Add language" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="3">
<ComboBox fx:id="regionComboBox" onAction="#onSelectRegion" prefWidth="150.0" promptText="Select region"/>
<ComboBox fx:id="countryComboBox" onAction="#onAddCountry" visible="false" prefWidth="150.0" promptText="Add country"/>
</HBox>
<Button onAction="#onAddArbitrator" text="Add arbitrator" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
</children>
<columnConstraints>
<ColumnConstraints/>
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" prefWidth="100.0"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="ALWAYS"/>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="NEVER"/>
</rowConstraints>
</GridPane>
</Tab>
<Tab text="Bank accounts" closable="false">
<GridPane hgap="5.0" vgap="5.0">
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0"/>
</padding>
<children>
<Label text="Bank account:"/>
<ComboBox fx:id="bankAccountComboBox" onAction="#selectBankAccount" GridPane.columnIndex="1"/>
<Label text="Bank account type:" GridPane.rowIndex="1"/>
<ComboBox fx:id="bankAccountTypesComboBox" promptText="Select bank account type" onAction="#selectBankAccountType" GridPane.rowIndex="1" GridPane.columnIndex="1"/>
<Label text="Bank account title:" GridPane.rowIndex="2"/>
<TextField fx:id="bankAccountTitleTextField" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
<Label text="Bank account holder name" GridPane.rowIndex="3"/>
<TextField fx:id="bankAccountHolderNameTextField" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
<Label text="Bank account primary ID" GridPane.rowIndex="4"/>
<TextField fx:id="bankAccountPrimaryIDTextField" GridPane.columnIndex="1" GridPane.rowIndex="4"/>
<Label text="Bank account secondary ID" GridPane.rowIndex="5"/>
<TextField fx:id="bankAccountSecondaryIDTextField" GridPane.columnIndex="1" GridPane.rowIndex="5"/>
<Label text="Currency used for bank account:" GridPane.rowIndex="6"/>
<ComboBox fx:id="bankAccountCurrencyComboBox" promptText="Select currency" GridPane.columnIndex="1" GridPane.rowIndex="6"/>
<Label text="Country of bank account" GridPane.rowIndex="7"/>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="7">
<ComboBox fx:id="bankAccountRegionComboBox" onAction="#onSelectBankAccountRegion" prefWidth="150.0" promptText="Select region"/>
<ComboBox fx:id="bankAccountCountryComboBox" visible="false" prefWidth="150.0" promptText="Select country"/>
</HBox>
<HBox spacing="10" GridPane.columnIndex="1" GridPane.rowIndex="8">
<Button fx:id="saveBankAccountButton" defaultButton="true" onAction="#onSaveBankAccount" text="Save bank account"/>
<Button fx:id="addBankAccountButton" onAction="#onAddBankAccount" text="Add new bank account"/>
<Button fx:id="removeBankAccountButton" onAction="#onRemoveBankAccount" text="Remove bank account"/>
</HBox>
</children>
<columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES"/>
<ColumnConstraints hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
<RowConstraints vgrow="NEVER"/>
</rowConstraints>
</GridPane>
</Tab>
</TabPane>
</AnchorPane>

View file

@ -6,20 +6,22 @@ import com.google.inject.Inject;
import de.jensd.fx.fontawesome.AwesomeDude; import de.jensd.fx.fontawesome.AwesomeDude;
import de.jensd.fx.fontawesome.AwesomeIcon; import de.jensd.fx.fontawesome.AwesomeIcon;
import io.bitsquare.bank.BankAccount; import io.bitsquare.bank.BankAccount;
import io.bitsquare.bank.BankAccountType; import io.bitsquare.bank.BankAccountTypeInfo;
import io.bitsquare.btc.WalletFacade; import io.bitsquare.btc.WalletFacade;
import io.bitsquare.gui.ChildController; import io.bitsquare.gui.ChildController;
import io.bitsquare.gui.NavigationController; import io.bitsquare.gui.NavigationController;
import io.bitsquare.gui.components.NetworkSyncPane; import io.bitsquare.gui.components.NetworkSyncPane;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import io.bitsquare.gui.util.ConfidenceDisplay; import io.bitsquare.gui.util.ConfidenceDisplay;
import io.bitsquare.gui.util.Localisation;
import io.bitsquare.gui.util.Popups; import io.bitsquare.gui.util.Popups;
import io.bitsquare.gui.util.Verification; import io.bitsquare.locale.Country;
import io.bitsquare.locale.CountryUtil;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.Localisation;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.storage.Storage; import io.bitsquare.storage.Storage;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.DSAKeyUtil; import io.bitsquare.util.DSAKeyUtil;
import io.bitsquare.util.Utilities;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
@ -36,7 +38,6 @@ import java.math.BigInteger;
import java.net.URL; import java.net.URL;
import java.util.Currency; import java.util.Currency;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class SetupController implements Initializable, ChildController public class SetupController implements Initializable, ChildController
@ -63,13 +64,13 @@ public class SetupController implements Initializable, ChildController
@FXML @FXML
private Accordion accordion; private Accordion accordion;
@FXML @FXML
private ComboBox<Locale> countryComboBox; private ComboBox<Country> countryComboBox;
@FXML @FXML
private ComboBox<BankAccountType> bankAccountTypesComboBox; private ComboBox<BankAccountTypeInfo> bankAccountTypesComboBox;
@FXML @FXML
private ComboBox<Currency> currencyComboBox; private ComboBox<Currency> currencyComboBox;
@FXML @FXML
private ProgressIndicator progressIndicator; private ConfidenceProgressIndicator progressIndicator;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -184,7 +185,7 @@ public class SetupController implements Initializable, ChildController
public void onClose(ActionEvent actionEvent) public void onClose(ActionEvent actionEvent)
{ {
navigationController.navigateToView(NavigationController.FUNDS, ""); navigationController.navigateToView(NavigationController.FUNDS);
} }
@ -263,20 +264,20 @@ public class SetupController implements Initializable, ChildController
"That data will be stored in the blockchain in a way that your privacy is protected.\n" + "That data will be stored in the blockchain in a way that your privacy is protected.\n" +
"Only your trading partners will be able to read those data, so your privacy will be protected."); "Only your trading partners will be able to read those data, so your privacy will be protected.");
bankAccountTypesComboBox.setItems(FXCollections.observableArrayList(Utilities.getAllBankAccountTypes())); bankAccountTypesComboBox.setItems(FXCollections.observableArrayList(BankAccountTypeInfo.getAllBankAccountTypeInfoObjects()));
currencyComboBox.setItems(FXCollections.observableArrayList(Utilities.getAllCurrencies())); currencyComboBox.setItems(FXCollections.observableArrayList(CurrencyUtil.getAllCurrencies()));
countryComboBox.setItems(FXCollections.observableArrayList(Utilities.getAllLocales())); countryComboBox.setItems(FXCollections.observableArrayList(CountryUtil.getAllCountries()));
bankAccountTypesComboBox.setConverter(new StringConverter<BankAccountType>() bankAccountTypesComboBox.setConverter(new StringConverter<BankAccountTypeInfo>()
{ {
@Override @Override
public String toString(BankAccountType bankAccountType) public String toString(BankAccountTypeInfo bankAccountTypeInfo)
{ {
return Localisation.get(bankAccountType.toString()); return Localisation.get(bankAccountTypeInfo.toString());
} }
@Override @Override
public BankAccountType fromString(String s) public BankAccountTypeInfo fromString(String s)
{ {
return null; return null;
} }
@ -297,23 +298,23 @@ public class SetupController implements Initializable, ChildController
} }
}); });
countryComboBox.setConverter(new StringConverter<Locale>() countryComboBox.setConverter(new StringConverter<Country>()
{ {
@Override @Override
public String toString(Locale locale) public String toString(Country country)
{ {
return locale.getDisplayCountry(); return country.getName();
} }
@Override @Override
public Locale fromString(String s) public Country fromString(String s)
{ {
return null; return null;
} }
}); });
bankAccountTypesComboBox.valueProperty().addListener((ov, oldValue, newValue) -> { bankAccountTypesComboBox.valueProperty().addListener((ov, oldValue, newValue) -> {
if (newValue != null && newValue instanceof BankAccountType) if (newValue != null && newValue instanceof BankAccountTypeInfo)
{ {
accountPrimaryID.setText(""); accountPrimaryID.setText("");
accountPrimaryID.setPromptText(newValue.getPrimaryIDName()); accountPrimaryID.setPromptText(newValue.getPrimaryIDName());
@ -379,18 +380,13 @@ public class SetupController implements Initializable, ChildController
private boolean verifyBankAccountData() private boolean verifyBankAccountData()
{ {
boolean accountIDsByBankTransferTypeValid = Verification.verifyAccountIDsByBankTransferType(bankAccountTypesComboBox.getSelectionModel().getSelectedItem(),
accountPrimaryID.getText(),
accountSecondaryID.getText());
return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null return bankAccountTypesComboBox.getSelectionModel().getSelectedItem() != null
&& countryComboBox.getSelectionModel().getSelectedItem() != null && countryComboBox.getSelectionModel().getSelectedItem() != null
&& currencyComboBox.getSelectionModel().getSelectedItem() != null && currencyComboBox.getSelectionModel().getSelectedItem() != null
&& accountTitle.getText().length() > 0 && accountTitle.getText().length() > 0
&& accountHolderName.getText().length() > 0 && accountHolderName.getText().length() > 0
&& accountPrimaryID.getText().length() > 0 && accountPrimaryID.getText().length() > 0
&& accountSecondaryID.getText().length() > 0 && accountSecondaryID.getText().length() > 0;
&& accountIDsByBankTransferTypeValid;
} }
} }

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<?import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator?>
<?import javafx.geometry.Insets?> <?import javafx.geometry.Insets?>
<?import javafx.scene.control.*?> <?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.*?>
@ -36,12 +37,12 @@
<Label text="Balance:" GridPane.rowIndex="1"/> <Label text="Balance:" GridPane.rowIndex="1"/>
<TextField fx:id="balanceTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/> <TextField fx:id="balanceTextField" editable="false" GridPane.columnIndex="1" GridPane.rowIndex="1"/>
<ProgressIndicator fx:id="progressIndicator" id="confidence-progress-indicator" GridPane.columnIndex="2" GridPane.halignment="LEFT" <ConfidenceProgressIndicator fx:id="progressIndicator" GridPane.columnIndex="2" GridPane.halignment="LEFT"
GridPane.rowIndex="1" GridPane.rowSpan="2" GridPane.valignment="TOP"> GridPane.rowIndex="1" GridPane.rowSpan="2" GridPane.valignment="TOP">
<GridPane.margin> <GridPane.margin>
<Insets top="2.0"/> <Insets top="2.0"/>
</GridPane.margin> </GridPane.margin>
</ProgressIndicator> </ConfidenceProgressIndicator>
<Label fx:id="confirmationLabel" text="Checking confirmations..." GridPane.columnIndex="3" GridPane.rowIndex="1"/> <Label fx:id="confirmationLabel" text="Checking confirmations..." GridPane.columnIndex="3" GridPane.rowIndex="1"/>
<Button fx:id="paymentDoneButton" defaultButton="true" onAction="#onPaymentDone" text="Payment done" disable="true" GridPane.columnIndex="1" <Button fx:id="paymentDoneButton" defaultButton="true" onAction="#onPaymentDone" text="Payment done" disable="true" GridPane.columnIndex="1"

View file

@ -0,0 +1,37 @@
package io.bitsquare.gui.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BitSquareConverter
{
private static final Logger log = LoggerFactory.getLogger(BitSquareConverter.class);
/**
* @param input String to be converted to a double. Both decimal points "." and "," are supported. Thousands separator is not supported.
* @return Returns a double value. Any invalid value returns Double.NEGATIVE_INFINITY.
*/
public static double stringToDouble(String input)
{
try
{
return stringToDouble2(input);
} catch (NumberFormatException | NullPointerException e)
{
return Double.NEGATIVE_INFINITY;
}
}
/**
* @param input String to be converted to a double. Both decimal points "." and "," are supported. Thousands separator is not supported.
* @return Returns a double value. Any invalid value throws an exception.
*/
public static double stringToDouble2(String input)
{
input = input.replace(",", ".");
return Double.parseDouble(input);
}
}

View file

@ -1,13 +1,16 @@
package io.bitsquare.gui.util; package io.bitsquare.gui.util;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.Localisation;
import io.bitsquare.trade.Direction; import io.bitsquare.trade.Direction;
import io.bitsquare.user.Arbitrator;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.Currency; import java.util.Currency;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
public class Formatter public class BitSquareFormatter
{ {
public static String formatPrice(double price) public static String formatPrice(double price)
{ {
@ -111,15 +114,15 @@ public class Formatter
return value * 100 + "%"; return value * 100 + "%";
} }
public static String countryLocalesToString(List<Locale> countryLocales) public static String countryLocalesToString(List<Country> countries)
{ {
String result = ""; String result = "";
int i = 0; int i = 0;
for (Locale locale : countryLocales) for (Country country : countries)
{ {
result += locale.getCountry(); result += country.getName();
i++; i++;
if (i < countryLocales.size()) if (i < countries.size())
result += ", "; result += ", ";
} }
return result; return result;
@ -139,4 +142,31 @@ public class Formatter
return result; return result;
} }
public static String arbitrationMethodsToString(List<Arbitrator.METHODS> items)
{
String result = "";
int i = 0;
for (Arbitrator.METHODS item : items)
{
result += Localisation.get(item.toString());
i++;
if (i < items.size())
result += ", ";
}
return result;
}
public static String arbitrationIDVerificationsToString(List<Arbitrator.ID_VERIFICATIONS> items)
{
String result = "";
int i = 0;
for (Arbitrator.ID_VERIFICATIONS item : items)
{
result += Localisation.get(item.toString());
i++;
if (i < items.size())
result += ", ";
}
return result;
}
} }

View file

@ -0,0 +1,130 @@
package io.bitsquare.gui.util;
import io.bitsquare.bank.BankAccountTypeInfo;
import javafx.scene.control.TextField;
import javafx.scene.effect.BlurType;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Effect;
import javafx.scene.paint.Color;
public class BitSquareValidator
{
private static Effect invalidEffect = new DropShadow(BlurType.GAUSSIAN, Color.RED, 4, 0.0, 0, 0);
private static String invalidStyle = "-fx-border-color: red";
public static class ValidationException extends Exception
{
}
public static void resetTextFields(TextField[] textFields)
{
for (int i = 0; i < textFields.length; i++)
{
TextField textField = textFields[i];
textField.setStyle("-fx-border-color: null");
textField.setEffect(null);
}
}
public static void textFieldsNotEmpty(TextField[] textFields) throws ValidationException
{
for (int i = 0; i < textFields.length; i++)
{
TextField textField = textFields[i];
textFieldNotEmpty(textField);
}
}
public static void textFieldNotEmpty(TextField textField) throws ValidationException
{
if (!validateStringNotEmpty(textField.getText()))
{
textField.setEffect(invalidEffect);
textField.setStyle(invalidStyle);
throw new ValidationException();
}
}
public static void textFieldsHasDoubleValue(TextField[] textFields) throws ValidationException
{
for (int i = 0; i < textFields.length; i++)
{
TextField textField = textFields[i];
textFieldHasDoubleValue(textField);
}
}
public static void textFieldHasDoubleValue(TextField textField) throws ValidationException
{
if (!validateStringAsDouble(textField.getText()))
{
textField.setEffect(invalidEffect);
textField.setStyle(invalidStyle);
throw new ValidationException();
}
}
//TODO
public static void textFieldBankAccountPrimaryIDIsValid(TextField textField, BankAccountTypeInfo bankAccountTypeInfo) throws ValidationException
{
if (!validateStringNotEmpty(textField.getText()))
{
textField.setEffect(invalidEffect);
textField.setStyle(invalidStyle);
throw new ValidationException();
}
}
public static void textFieldBankAccountSecondaryIDIsValid(TextField textField, BankAccountTypeInfo bankAccountTypeInfo) throws ValidationException
{
if (!validateStringNotEmpty(textField.getText()))
{
textField.setEffect(invalidEffect);
textField.setStyle(invalidStyle);
throw new ValidationException();
}
}
public static boolean validateStringsAsDouble(String[] inputs)
{
boolean result = true;
for (int i = 0; i < inputs.length; i++)
{
String input = inputs[i];
result &= validateStringAsDouble(input);
}
return result;
}
public static boolean validateStringAsDouble(String input)
{
try
{
input = input.replace(",", ".");
Double.parseDouble(input);
return true;
} catch (NumberFormatException | NullPointerException e)
{
return false;
}
}
public static boolean validateStringsNotEmpty(String[] inputs)
{
boolean result = true;
for (int i = 0; i < inputs.length; i++)
{
String input = inputs[i];
result &= validateStringNotEmpty(input);
}
return result;
}
public static boolean validateStringNotEmpty(String input)
{
return input != null && input.length() > 0 && !input.equals(" ");
}
}

View file

@ -2,8 +2,8 @@ package io.bitsquare.gui.util;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import com.google.bitcoin.script.Script; import com.google.bitcoin.script.Script;
import io.bitsquare.gui.components.confidence.ConfidenceProgressIndicator;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -22,7 +22,7 @@ public class ConfidenceDisplay
private Label confirmationLabel; private Label confirmationLabel;
private TextField balanceTextField; private TextField balanceTextField;
private Transaction transaction; private Transaction transaction;
private ProgressIndicator progressIndicator; private ConfidenceProgressIndicator progressIndicator;
/** /**
* We got the confidence for the actual updating tx. * We got the confidence for the actual updating tx.
@ -32,7 +32,7 @@ public class ConfidenceDisplay
* @param balanceTextField * @param balanceTextField
* @param progressIndicator * @param progressIndicator
*/ */
public ConfidenceDisplay(Wallet wallet, Label confirmationLabel, TextField balanceTextField, ProgressIndicator progressIndicator) public ConfidenceDisplay(Wallet wallet, Label confirmationLabel, TextField balanceTextField, ConfidenceProgressIndicator progressIndicator)
{ {
this.wallet = wallet; this.wallet = wallet;
this.confirmationLabel = confirmationLabel; this.confirmationLabel = confirmationLabel;
@ -96,7 +96,7 @@ public class ConfidenceDisplay
* @param transaction We want the confidence for only that tx, not the lasted changed in the wallet * @param transaction We want the confidence for only that tx, not the lasted changed in the wallet
* @param progressIndicator * @param progressIndicator
*/ */
public ConfidenceDisplay(Wallet wallet, Label confirmationLabel, final Transaction transaction, ProgressIndicator progressIndicator) public ConfidenceDisplay(Wallet wallet, Label confirmationLabel, final Transaction transaction, ConfidenceProgressIndicator progressIndicator)
{ {
this.wallet = wallet; this.wallet = wallet;
this.confirmationLabel = confirmationLabel; this.confirmationLabel = confirmationLabel;

View file

@ -1,30 +0,0 @@
package io.bitsquare.gui.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Locale;
public class Converter
{
private static final Logger log = LoggerFactory.getLogger(Converter.class);
public static double stringToDouble(String input)
{
if (input == null || input.equals(""))
return 0;
try
{
DecimalFormat decimalFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.getDefault());
Object d = decimalFormat.getDecimalFormatSymbols();
return decimalFormat.parse(input).doubleValue();
} catch (ParseException e)
{
log.warn(e.toString());
return 0;
}
}
}

View file

@ -1,6 +1,6 @@
package io.bitsquare.gui.util; package io.bitsquare.gui.util;
import io.bitsquare.bank.BankAccountType; import io.bitsquare.bank.BankAccountTypeInfo;
import io.bitsquare.gui.components.VSpacer; import io.bitsquare.gui.components.VSpacer;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -86,10 +86,10 @@ public class FormBuilder
return comboBox; return comboBox;
} }
public static ComboBox<BankAccountType> addBankAccountComboBox(GridPane gridPane, String title, List<BankAccountType> list, int row) public static ComboBox<BankAccountTypeInfo> addBankAccountComboBox(GridPane gridPane, String title, List<BankAccountTypeInfo> list, int row)
{ {
gridPane.add(new Label(title), 0, row); gridPane.add(new Label(title), 0, row);
ComboBox<BankAccountType> comboBox = new ComboBox<>(FXCollections.observableArrayList(list)); ComboBox<BankAccountTypeInfo> comboBox = new ComboBox<>(FXCollections.observableArrayList(list));
gridPane.add(comboBox, 1, row); gridPane.add(comboBox, 1, row);
return comboBox; return comboBox;
} }

View file

@ -6,15 +6,21 @@ import javafx.scene.image.ImageView;
public class Icons public class Icons
{ {
public static final String HOME = "/images/nav/home.png"; public static final String HOME = "/images/nav/home.png";
public static final String HOME_ACTIVE = "/images/nav/home_active.png";
public static final String NAV_BUY = "/images/nav/nav_buy.png"; public static final String NAV_BUY = "/images/nav/nav_buy.png";
public static final String NAV_BUY_ACTIVE = "/images/nav/nav_buy_active.png"; public static final String NAV_BUY_ACTIVE = "/images/nav/nav_buy_active.png";
public static final String NAV_SELL = "/images/nav/nav_sell.png"; public static final String NAV_SELL = "/images/nav/nav_sell.png";
public static final String NAV_SELL_ACTIVE = "/images/nav/nav_sell_active.png"; public static final String NAV_SELL_ACTIVE = "/images/nav/nav_sell_active.png";
public static final String ORDERS = "/images/nav/orders.png"; public static final String ORDERS = "/images/nav/orders.png";
public static final String ORDERS_ACTIVE = "/images/nav/orders_active.png";
public static final String HISTORY = "/images/nav/history.png"; public static final String HISTORY = "/images/nav/history.png";
public static final String HISTORY_ACTIVE = "/images/nav/history_active.png";
public static final String FUNDS = "/images/nav/funds.png"; public static final String FUNDS = "/images/nav/funds.png";
public static final String FUNDS_ACTIVE = "/images/nav/funds_active.png";
public static final String MSG = "/images/nav/msg.png"; public static final String MSG = "/images/nav/msg.png";
public static final String MSG_ACTIVE = "/images/nav/msg_active.png";
public static final String SETTINGS = "/images/nav/settings.png"; public static final String SETTINGS = "/images/nav/settings.png";
public static final String SETTINGS_ACTIVE = "/images/nav/settings_active.png";
public static final String MSG_ALERT = "/images/nav/alertRound.png"; public static final String MSG_ALERT = "/images/nav/alertRound.png";

View file

@ -1,7 +1,10 @@
package io.bitsquare.gui.util; package io.bitsquare.gui.util;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialogs; import org.controlsfx.dialog.Dialogs;
import java.util.List;
public class Popups public class Popups
{ {
public static void openErrorPopup(String title, String message) public static void openErrorPopup(String title, String message)
@ -23,4 +26,17 @@ public class Popups
.lightweight() .lightweight()
.showWarning(); .showWarning();
} }
public static Action openRegistrationMissingPopup(String title, String message, String masthead, List<Dialogs.CommandLink> commandLinks, int selectedIndex)
{
return Dialogs.create()
.title(title)
.message(message)
.masthead(masthead)
.nativeTitleBar()
.lightweight()
.showCommandLinks(commandLinks.get(selectedIndex), commandLinks);
}
} }

View file

@ -1,22 +0,0 @@
package io.bitsquare.gui.util;
import com.google.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Verification
{
private static final Logger log = LoggerFactory.getLogger(Verification.class);
@Inject
public Verification()
{
}
// TODO define rules for prim. and sec. ID per bank account type
public static boolean verifyAccountIDsByBankTransferType(Object bankTransferTypeSelectedItem, String accountPrimaryID, String accountSecondaryID)
{
return true;
}
}

View file

@ -0,0 +1,63 @@
package io.bitsquare.locale;
import java.io.Serializable;
import java.util.Objects;
public class Country implements Serializable
{
private static final long serialVersionUID = -5930294199097793187L;
private String code;
private String name;
private Region region;
public Country(String code, String name, Region region)
{
this.code = code;
this.name = name;
this.region = region;
}
public int hashCode()
{
return Objects.hashCode(code);
}
public boolean equals(Object obj)
{
if (!(obj instanceof Country))
return false;
if (obj == this)
return true;
Country other = (Country) obj;
return other.getCode().equals(code);
}
public String getCode()
{
return code;
}
public String getName()
{
return name;
}
public Region getRegion()
{
return region;
}
@Override
public String toString()
{
return "code='" + code + '\'' +
", name='" + name + '\'' +
", getRegion='" + region;
}
}

View file

@ -0,0 +1,359 @@
package io.bitsquare.locale;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import javax.annotation.Nullable;
import java.util.*;
public class CountryUtil
{
public static List<Region> getAllRegions()
{
List<Region> allRegions = new ArrayList<>();
String regionCode = "NA";
Region region = new Region(regionCode, getRegionName(regionCode));
allRegions.add(region);
regionCode = "SA";
region = new Region(regionCode, getRegionName(regionCode));
allRegions.add(region);
regionCode = "AF";
region = new Region(regionCode, getRegionName(regionCode));
allRegions.add(region);
regionCode = "EU";
region = new Region(regionCode, getRegionName(regionCode));
allRegions.add(region);
regionCode = "AS";
region = new Region(regionCode, getRegionName(regionCode));
allRegions.add(region);
regionCode = "OC";
region = new Region(regionCode, getRegionName(regionCode));
allRegions.add(region);
return allRegions;
}
public static List<Country> getAllCountriesFor(Region selectedRegion)
{
List<Country> allCountries = getAllCountries();
List<Country> filteredList = Lists.newArrayList(Collections2.filter(allCountries, new Predicate<Country>()
{
@Override
public boolean apply(@Nullable Country country)
{
if (selectedRegion != null && country != null)
return country.getRegion().equals(selectedRegion);
else
return false;
}
}));
return filteredList;
}
public static List<Country> getAllCountries()
{
List<Locale> allCountryLocales = getAllCountryLocales();
List<Country> allCountries = new ArrayList<>();
for (int i = 0; i < allCountryLocales.size(); i++)
{
Locale locale = allCountryLocales.get(i);
String regionCode = getRegionCode(locale.getCountry());
Region region = new Region(regionCode, getRegionName(regionCode));
Country country = new Country(locale.getCountry(), locale.getDisplayCountry(), region);
allCountries.add(country);
}
return allCountries;
}
public static Country getDefaultCountry()
{
Locale locale = new Locale("", Locale.getDefault().getCountry());
String regionCode = getRegionCode(locale.getCountry());
Region region = new Region(regionCode, getRegionName(regionCode));
return new Country(locale.getCountry(), locale.getDisplayCountry(), region);
}
private static List<Locale> getAllCountryLocales()
{
List<Locale> allLocales = Arrays.asList(Locale.getAvailableLocales());
Set<Locale> allLocalesAsSet = new HashSet<>();
for (int i = 0; i < allLocales.size(); i++)
{
Locale locale = allLocales.get(i);
if (!locale.getCountry().equals(""))
{
allLocalesAsSet.add(new Locale("", locale.getCountry(), ""));
}
}
allLocales = new ArrayList<>();
allLocales.addAll(allLocalesAsSet);
allLocales.sort(new Comparator<Locale>()
{
@Override
public int compare(Locale locale1, Locale locale2)
{
return locale1.getDisplayCountry().compareTo(locale2.getDisplayCountry());
}
});
return allLocales;
}
private static String getRegionCode(String countryCode)
{
if (countryCode.length() > 0 && countryCodeList.contains(countryCode))
{
int index = countryCodeList.indexOf(countryCode);
return regionCodeList.get(index).toString();
}
else
{
return "Undefined";
}
}
public static String getRegionName(String regionCode)
{
for (String[] regionName : regionCodeToName)
{
if (regionName[0].equals(regionCode))
{
return regionName[1];
}
}
return regionCode;
}
private static String[] countryCodes = new String[]{"AE",
"AL",
"AR",
"AT",
"AU",
"BA",
"BE",
"BG",
"BH",
"BO",
"BR",
"BY",
"CA",
"CH",
"CL",
"CN",
"CO",
"CR",
"CS",
"CU",
"CY",
"CZ",
"DE",
"DK",
"DO",
"DZ",
"EC",
"EE",
"EG",
"ES",
"FI",
"FR",
"GB",
"GR",
"GT",
"HK",
"HN",
"HR",
"HU",
"ID",
"IE",
"IL",
"IN",
"IQ",
"IS",
"IT",
"JO",
"JP",
"KR",
"KW",
"LB",
"LT",
"LU",
"LV",
"LY",
"MA",
"ME",
"MK",
"MT",
"MX",
"MY",
"NI",
"NL",
"NO",
"NZ",
"OM",
"PA",
"PE",
"PH",
"PL",
"PR",
"PT",
"PY",
"QA",
"RO",
"RS",
"RU",
"SA",
"SD",
"SE",
"SG",
"SI",
"SK",
"SV",
"SY",
"TH",
"TN",
"TR",
"TW",
"UA",
"US",
"UY",
"VE",
"VN",
"YE",
"ZA"
};
private static String[] regionCodes = new String[]{
"AS",
"EU",
"SA",
"EU",
"OC",
"EU",
"EU",
"EU",
"AS",
"SA",
"SA",
"EU",
"NA",
"EU",
"SA",
"AS",
"SA",
"NA",
"EU",
"NA",
"AS",
"EU",
"EU",
"EU",
"NA",
"AF",
"SA",
"EU",
"AF",
"EU",
"EU",
"EU",
"EU",
"EU",
"NA",
"AS",
"NA",
"EU",
"EU",
"AS",
"EU",
"AS",
"AS",
"AS",
"EU",
"EU",
"AS",
"AS",
"AS",
"AS",
"AS",
"EU",
"EU",
"EU",
"AF",
"AF",
"EU",
"EU",
"EU",
"NA",
"AS",
"NA",
"EU",
"EU",
"OC",
"AS",
"NA",
"SA",
"AS",
"EU",
"NA",
"EU",
"SA",
"AS",
"EU",
"EU",
"EU",
"AS",
"AF",
"EU",
"AS",
"EU",
"EU",
"NA",
"AS",
"AS",
"AF",
"AS",
"AS",
"EU",
"NA",
"SA",
"SA",
"AS",
"AS",
"AF"
};
private static List<String> regionCodeList;
private static List<String> countryCodeList;
static
{
if (countryCodeList == null)
{
countryCodeList = Arrays.asList(countryCodes);
}
if (regionCodeList == null)
{
regionCodeList = Arrays.asList(regionCodes);
}
}
private static String[][] regionCodeToName = new String[][]{
{"NA", "North America"},
{"SA", "South America"},
{"AF", "Africa"},
{"EU", "Europe"},
{"AS", "Asia"},
{"OC", "Oceania"}
};
}

View file

@ -0,0 +1,50 @@
package io.bitsquare.locale;
import java.text.NumberFormat;
import java.util.*;
public class CurrencyUtil
{
public static List<Currency> getAllCurrencies()
{
ArrayList<Currency> mainCurrencies = new ArrayList<>();
mainCurrencies.add(Currency.getInstance("USD"));
mainCurrencies.add(Currency.getInstance("EUR"));
mainCurrencies.add(Currency.getInstance("CNY"));
mainCurrencies.add(Currency.getInstance("RUB"));
mainCurrencies.add(Currency.getInstance("JPY"));
mainCurrencies.add(Currency.getInstance("GBP"));
mainCurrencies.add(Currency.getInstance("CAD"));
mainCurrencies.add(Currency.getInstance("AUD"));
mainCurrencies.add(Currency.getInstance("CHF"));
mainCurrencies.add(Currency.getInstance("CNY"));
Set<Currency> allCurrenciesSet = Currency.getAvailableCurrencies();
allCurrenciesSet.removeAll(mainCurrencies);
List<Currency> allCurrenciesList = new ArrayList<>(allCurrenciesSet);
allCurrenciesList.sort(new Comparator<Currency>()
{
@Override
public int compare(Currency a, Currency b)
{
return a.getCurrencyCode().compareTo(b.getCurrencyCode());
}
});
List<Currency> resultList = new ArrayList<>(mainCurrencies);
resultList.addAll(allCurrenciesList);
Currency defaultCurrency = Currency.getInstance(Locale.getDefault());
resultList.remove(defaultCurrency);
resultList.add(0, defaultCurrency);
return resultList;
}
public static Currency getDefaultCurrency()
{
return NumberFormat.getNumberInstance(Locale.getDefault()).getCurrency();
}
}

View file

@ -0,0 +1,54 @@
package io.bitsquare.locale;
import java.util.*;
public class LanguageUtil
{
/*public static List<Locale> getPopularLanguages()
{
List<Locale> list = new ArrayList<>();
list.add(new Locale("de", "AT"));
list.add(new Locale("de", "DE"));
list.add(new Locale("en", "US"));
list.add(new Locale("en", "UK"));
list.add(new Locale("es", "ES"));
list.add(new Locale("ru", "RU"));
list.add(new Locale("zh", "CN"));
list.add(new Locale("en", "AU"));
list.add(new Locale("it", "IT"));
list.add(new Locale("en", "CA"));
return list;
} */
public static List<Locale> getAllLanguageLocales()
{
List<Locale> allLocales = Arrays.asList(Locale.getAvailableLocales());
Set<Locale> allLocalesAsSet = new HashSet<>();
for (int i = 0; i < allLocales.size(); i++)
{
Locale locale = allLocales.get(i);
if (!locale.getLanguage().equals(""))
{
allLocalesAsSet.add(new Locale(locale.getLanguage(), ""));
}
}
allLocales = new ArrayList<>();
allLocales.addAll(allLocalesAsSet);
allLocales.sort(new Comparator<Locale>()
{
@Override
public int compare(Locale locale1, Locale locale2)
{
return locale1.getDisplayLanguage().compareTo(locale2.getDisplayLanguage());
}
});
return allLocales;
}
public static Locale getDefaultLanguageLocale()
{
return new Locale(Locale.getDefault().getLanguage(), "");
}
}

View file

@ -1,4 +1,7 @@
package io.bitsquare.gui.util; package io.bitsquare.locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -7,11 +10,14 @@ import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Locale; import java.util.Locale;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle; import java.util.PropertyResourceBundle;
import java.util.ResourceBundle; import java.util.ResourceBundle;
public class Localisation public class Localisation
{ {
private static final Logger log = LoggerFactory.getLogger(Localisation.class);
public static ResourceBundle getResourceBundle() public static ResourceBundle getResourceBundle()
{ {
return ResourceBundle.getBundle("i18n.displayStrings", new UTF8Control()); return ResourceBundle.getBundle("i18n.displayStrings", new UTF8Control());
@ -19,7 +25,15 @@ public class Localisation
public static String get(String key) public static String get(String key)
{ {
return Localisation.getResourceBundle().getString(key); try
{
return Localisation.getResourceBundle().getString(key);
} catch (MissingResourceException e)
{
log.error("MissingResourceException for key: " + key);
log.error("MissingResourceException for key: " + key);
return key + " is missing";
}
} }
public static String get(String key, String... arguments) public static String get(String key, String... arguments)

View file

@ -0,0 +1,51 @@
package io.bitsquare.locale;
import java.io.Serializable;
import java.util.Objects;
public class Region implements Serializable
{
private static final long serialVersionUID = -5930294199097793187L;
private String code;
private String name;
public Region(String code, String name)
{
this.code = code;
this.name = name;
}
public int hashCode()
{
return Objects.hashCode(code);
}
public boolean equals(Object obj)
{
if (!(obj instanceof Region))
return false;
if (obj == this)
return true;
Region other = (Region) obj;
return other.getCode().equals(code);
}
public String getCode()
{
return code;
}
public String getName()
{
return name;
}
@Override
public String toString()
{
return "regionCode='" + code + '\'' +
", continentName='" + name;
}
}

View file

@ -4,8 +4,9 @@ import com.google.inject.Inject;
import io.bitsquare.BitSquare; import io.bitsquare.BitSquare;
import io.bitsquare.msg.listeners.*; import io.bitsquare.msg.listeners.*;
import io.bitsquare.trade.Offer; import io.bitsquare.trade.Offer;
import io.bitsquare.trade.offerer.OffererPaymentProtocol; import io.bitsquare.trade.payment.offerer.OffererPaymentProtocol;
import io.bitsquare.trade.taker.TakerPaymentProtocol; import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
import io.bitsquare.user.Arbitrator;
import io.bitsquare.util.DSAKeyUtil; import io.bitsquare.util.DSAKeyUtil;
import io.bitsquare.util.Utilities; import io.bitsquare.util.Utilities;
import javafx.application.Platform; import javafx.application.Platform;
@ -51,6 +52,7 @@ public class MessageFacade
private Peer masterPeer; private Peer masterPeer;
private List<OrderBookListener> orderBookListeners = new ArrayList<>(); private List<OrderBookListener> orderBookListeners = new ArrayList<>();
private List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>(); private List<TakeOfferRequestListener> takeOfferRequestListeners = new ArrayList<>();
private List<ArbitratorListener> arbitratorListeners = new ArrayList<>();
// //TODO change to map (key: offerID) instead of list (offererPaymentProtocols, takerPaymentProtocols) // //TODO change to map (key: offerID) instead of list (offererPaymentProtocols, takerPaymentProtocols)
private List<TakerPaymentProtocol> takerPaymentProtocols = new ArrayList<>(); private List<TakerPaymentProtocol> takerPaymentProtocols = new ArrayList<>();
@ -98,7 +100,7 @@ public class MessageFacade
try try
{ {
createMyPeerInstance(keyName, port); createMyPeerInstance(keyName, port);
setupStorage(); //setupStorage();
//TODO save periodically or get informed if network address changes //TODO save periodically or get informed if network address changes
saveMyAddressToDHT(); saveMyAddressToDHT();
setupReplyHandler(); setupReplyHandler();
@ -152,6 +154,55 @@ public class MessageFacade
myPeer.put(locationKey).setData(contentKey, reputationData).start(); myPeer.put(locationKey).setData(contentKey, reputationData).start();
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Arbitrators
///////////////////////////////////////////////////////////////////////////////////////////
public void addArbitrator(Arbitrator arbitrator) throws IOException
{
Number160 locationKey = Number160.createHash("Arbitrators");
final Number160 contentKey = Number160.createHash(arbitrator.getUID());
final Data arbitratorData = new Data(arbitrator);
//offerData.setTTLSeconds(5);
final FutureDHT addFuture = myPeer.put(locationKey).setData(contentKey, arbitratorData).start();
//final FutureDHT addFuture = myPeer.add(locationKey).setData(offerData).start();
addFuture.addListener(new BaseFutureAdapter<BaseFuture>()
{
@Override
public void operationComplete(BaseFuture future) throws Exception
{
Platform.runLater(() -> onArbitratorAdded(arbitratorData, future.isSuccess(), locationKey));
}
});
}
private void onArbitratorAdded(Data arbitratorData, boolean success, Number160 locationKey)
{
}
public void getArbitrators(Locale languageLocale)
{
final Number160 locationKey = Number160.createHash("Arbitrators");
final FutureDHT getArbitratorsFuture = myPeer.get(locationKey).setAll().start();
getArbitratorsFuture.addListener(new BaseFutureAdapter<BaseFuture>()
{
@Override
public void operationComplete(BaseFuture future) throws Exception
{
final Map<Number160, Data> dataMap = getArbitratorsFuture.getDataMap();
Platform.runLater(() -> onArbitratorsReceived(dataMap, future.isSuccess()));
}
});
}
private void onArbitratorsReceived(Map<Number160, Data> dataMap, boolean success)
{
for (ArbitratorListener arbitratorListener : arbitratorListeners)
arbitratorListener.onArbitratorsReceived(dataMap, success);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Publish offer // Publish offer
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -160,7 +211,7 @@ public class MessageFacade
public void addOffer(Offer offer) throws IOException public void addOffer(Offer offer) throws IOException
{ {
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
final Number160 contentKey = Number160.createHash(offer.getUid()); final Number160 contentKey = Number160.createHash(offer.getUID());
final Data offerData = new Data(offer); final Data offerData = new Data(offer);
//offerData.setTTLSeconds(5); //offerData.setTTLSeconds(5);
final FutureDHT addFuture = myPeer.put(locationKey).setData(contentKey, offerData).start(); final FutureDHT addFuture = myPeer.put(locationKey).setData(contentKey, offerData).start();
@ -216,7 +267,7 @@ public class MessageFacade
public void removeOffer(Offer offer) throws IOException public void removeOffer(Offer offer) throws IOException
{ {
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
Number160 contentKey = Number160.createHash(offer.getUid()); Number160 contentKey = Number160.createHash(offer.getUID());
log.debug("removeOffer"); log.debug("removeOffer");
FutureDHT removeFuture = myPeer.remove(locationKey).setReturnResults().setContentKey(contentKey).start(); FutureDHT removeFuture = myPeer.remove(locationKey).setReturnResults().setContentKey(contentKey).start();
removeFuture.addListener(new BaseFutureAdapter<BaseFuture>() removeFuture.addListener(new BaseFutureAdapter<BaseFuture>()
@ -636,6 +687,15 @@ public class MessageFacade
pingPeerListeners.remove(listener); pingPeerListeners.remove(listener);
} }
public void addArbitratorListener(ArbitratorListener listener)
{
arbitratorListeners.add(listener);
}
public void removeArbitratorListener(ArbitratorListener listener)
{
arbitratorListeners.remove(listener);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Private Methods // Private Methods

View file

@ -0,0 +1,15 @@
package io.bitsquare.msg.listeners;
import net.tomp2p.peers.Number160;
import net.tomp2p.storage.Data;
import java.util.Map;
public interface ArbitratorListener
{
void onArbitratorAdded(Data offerData, boolean success);
void onArbitratorsReceived(Map<Number160, Data> dataMap, boolean success);
void onArbitratorRemoved(Data data, boolean success);
}

View file

@ -1,6 +1,7 @@
package io.bitsquare.settings; package io.bitsquare.settings;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bitsquare.locale.Country;
import io.bitsquare.user.Arbitrator; import io.bitsquare.user.Arbitrator;
import java.io.Serializable; import java.io.Serializable;
@ -14,7 +15,7 @@ public class Settings implements Serializable
private static final long serialVersionUID = 7995048077355006861L; private static final long serialVersionUID = 7995048077355006861L;
private List<Locale> acceptedLanguageLocales = new ArrayList<>(); private List<Locale> acceptedLanguageLocales = new ArrayList<>();
private List<Locale> acceptedCountryLocales = new ArrayList<>(); private List<Country> acceptedCountryLocales = new ArrayList<>();
private List<Arbitrator> acceptedArbitrators = new ArrayList<>(); private List<Arbitrator> acceptedArbitrators = new ArrayList<>();
private int maxCollateral; private int maxCollateral;
private int minCollateral; private int minCollateral;
@ -38,7 +39,7 @@ public class Settings implements Serializable
if (savedSettings != null) if (savedSettings != null)
{ {
acceptedLanguageLocales = savedSettings.getAcceptedLanguageLocales(); acceptedLanguageLocales = savedSettings.getAcceptedLanguageLocales();
acceptedCountryLocales = savedSettings.getAcceptedCountryLocales(); acceptedCountryLocales = savedSettings.getAcceptedCountries();
acceptedArbitrators = savedSettings.getAcceptedArbitrators(); acceptedArbitrators = savedSettings.getAcceptedArbitrators();
maxCollateral = savedSettings.getMaxCollateral(); maxCollateral = savedSettings.getMaxCollateral();
minCollateral = savedSettings.getMinCollateral(); minCollateral = savedSettings.getMinCollateral();
@ -51,18 +52,33 @@ public class Settings implements Serializable
acceptedLanguageLocales.add(locale); acceptedLanguageLocales.add(locale);
} }
public void addAcceptedCountryLocale(Locale locale) public void removeAcceptedLanguageLocale(Locale item)
{
acceptedLanguageLocales.remove(item);
}
public void addAcceptedCountry(Country locale)
{ {
if (!acceptedCountryLocales.contains(locale)) if (!acceptedCountryLocales.contains(locale))
acceptedCountryLocales.add(locale); acceptedCountryLocales.add(locale);
} }
public void removeAcceptedCountry(Country item)
{
acceptedCountryLocales.remove(item);
}
public void addAcceptedArbitrator(Arbitrator arbitrator) public void addAcceptedArbitrator(Arbitrator arbitrator)
{ {
if (!acceptedArbitrators.contains(arbitrator)) if (!acceptedArbitrators.contains(arbitrator))
acceptedArbitrators.add(arbitrator); acceptedArbitrators.add(arbitrator);
} }
public void removeAcceptedArbitrator(Arbitrator item)
{
acceptedArbitrators.remove(item);
}
public void setMaxCollateral(int maxCollateral) public void setMaxCollateral(int maxCollateral)
{ {
this.maxCollateral = maxCollateral; this.maxCollateral = maxCollateral;
@ -87,7 +103,7 @@ public class Settings implements Serializable
return acceptedLanguageLocales; return acceptedLanguageLocales;
} }
public List<Locale> getAcceptedCountryLocales() public List<Country> getAcceptedCountries()
{ {
return acceptedCountryLocales; return acceptedCountryLocales;
} }
@ -117,4 +133,5 @@ public class Settings implements Serializable
return minCollateral; return minCollateral;
} }
} }

View file

@ -1,7 +1,8 @@
package io.bitsquare.trade; package io.bitsquare.trade;
import io.bitsquare.bank.BankAccountType; import io.bitsquare.bank.BankAccountTypeInfo;
import io.bitsquare.btc.BtcFormatter; import io.bitsquare.btc.BtcFormatter;
import io.bitsquare.locale.Country;
import io.bitsquare.user.Arbitrator; import io.bitsquare.user.Arbitrator;
import java.io.Serializable; import java.io.Serializable;
@ -25,11 +26,11 @@ public class Offer implements Serializable
private BigInteger amount; private BigInteger amount;
private BigInteger minAmount; private BigInteger minAmount;
private String messagePubKeyAsHex; private String messagePubKeyAsHex;
private BankAccountType.BankAccountTypeEnum bankAccountTypeEnum; private BankAccountTypeInfo.BankAccountType bankAccountType;
private Locale bankAccountCountryLocale; private Country bankAccountCountry;
private int collateral; private int collateral;
private List<Locale> acceptedCountryLocales; private List<Country> acceptedCountries;
private List<Locale> acceptedLanguageLocales; private List<Locale> acceptedLanguageLocales;
private String offerFeePaymentTxID; private String offerFeePaymentTxID;
private String bankAccountUID; private String bankAccountUID;
@ -45,13 +46,13 @@ public class Offer implements Serializable
double price, double price,
BigInteger amount, BigInteger amount,
BigInteger minAmount, BigInteger minAmount,
BankAccountType.BankAccountTypeEnum bankAccountTypeEnum, BankAccountTypeInfo.BankAccountType bankAccountType,
Currency currency, Currency currency,
Locale bankAccountCountryLocale, Country bankAccountCountry,
String bankAccountUID, String bankAccountUID,
Arbitrator arbitrator, Arbitrator arbitrator,
int collateral, int collateral,
List<Locale> acceptedCountryLocales, List<Country> acceptedCountries,
List<Locale> acceptedLanguageLocales) List<Locale> acceptedLanguageLocales)
{ {
this.messagePubKeyAsHex = messagePubKeyAsHex; this.messagePubKeyAsHex = messagePubKeyAsHex;
@ -59,13 +60,13 @@ public class Offer implements Serializable
this.price = price; this.price = price;
this.amount = amount; this.amount = amount;
this.minAmount = minAmount; this.minAmount = minAmount;
this.bankAccountTypeEnum = bankAccountTypeEnum; this.bankAccountType = bankAccountType;
this.currency = currency; this.currency = currency;
this.bankAccountCountryLocale = bankAccountCountryLocale; this.bankAccountCountry = bankAccountCountry;
this.bankAccountUID = bankAccountUID; this.bankAccountUID = bankAccountUID;
this.arbitrator = arbitrator; this.arbitrator = arbitrator;
this.collateral = collateral; this.collateral = collateral;
this.acceptedCountryLocales = acceptedCountryLocales; this.acceptedCountries = acceptedCountries;
this.acceptedLanguageLocales = acceptedLanguageLocales; this.acceptedLanguageLocales = acceptedLanguageLocales;
this.uid = UUID.randomUUID().toString(); this.uid = UUID.randomUUID().toString();
@ -91,7 +92,7 @@ public class Offer implements Serializable
return messagePubKeyAsHex; return messagePubKeyAsHex;
} }
public String getUid() public String getUID()
{ {
return uid; return uid;
} }
@ -116,9 +117,9 @@ public class Offer implements Serializable
return direction; return direction;
} }
public BankAccountType.BankAccountTypeEnum getBankAccountTypeEnum() public BankAccountTypeInfo.BankAccountType getBankAccountType()
{ {
return bankAccountTypeEnum; return bankAccountType;
} }
public Currency getCurrency() public Currency getCurrency()
@ -126,14 +127,14 @@ public class Offer implements Serializable
return currency; return currency;
} }
public Locale getBankAccountCountryLocale() public Country getBankAccountCountry()
{ {
return bankAccountCountryLocale; return bankAccountCountry;
} }
public List<Locale> getAcceptedCountryLocales() public List<Country> getAcceptedCountries()
{ {
return acceptedCountryLocales; return acceptedCountries;
} }
public List<Locale> getAcceptedLanguageLocales() public List<Locale> getAcceptedLanguageLocales()
@ -182,10 +183,10 @@ public class Offer implements Serializable
", amount=" + amount + ", amount=" + amount +
", minAmount=" + minAmount + ", minAmount=" + minAmount +
", messagePubKey=" + messagePubKeyAsHex.hashCode() + ", messagePubKey=" + messagePubKeyAsHex.hashCode() +
", bankAccountTypeEnum=" + bankAccountTypeEnum + ", bankAccountTypeEnum=" + bankAccountType +
", bankAccountCountryLocale=" + bankAccountCountryLocale + ", bankAccountCountryLocale=" + bankAccountCountry +
", collateral=" + collateral + ", collateral=" + collateral +
", acceptedCountryLocales=" + acceptedCountryLocales + ", acceptedCountryLocales=" + acceptedCountries +
", acceptedLanguageLocales=" + acceptedLanguageLocales + ", acceptedLanguageLocales=" + acceptedLanguageLocales +
", offerFeePaymentTxID='" + offerFeePaymentTxID + '\'' + ", offerFeePaymentTxID='" + offerFeePaymentTxID + '\'' +
", bankAccountUID='" + bankAccountUID + '\'' + ", bankAccountUID='" + bankAccountUID + '\'' +

View file

@ -95,7 +95,7 @@ public class Trade implements Serializable
public String getUid() public String getUid()
{ {
return offer.getUid(); return offer.getUID();
} }
public Offer getOffer() public Offer getOffer()

View file

@ -14,10 +14,10 @@ import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.TradeMessage; import io.bitsquare.msg.TradeMessage;
import io.bitsquare.settings.Settings; import io.bitsquare.settings.Settings;
import io.bitsquare.storage.Storage; import io.bitsquare.storage.Storage;
import io.bitsquare.trade.offerer.OffererPaymentProtocol; import io.bitsquare.trade.payment.offerer.OffererPaymentProtocol;
import io.bitsquare.trade.offerer.OffererPaymentProtocolListener; import io.bitsquare.trade.payment.offerer.OffererPaymentProtocolListener;
import io.bitsquare.trade.taker.TakerPaymentProtocol; import io.bitsquare.trade.payment.taker.TakerPaymentProtocol;
import io.bitsquare.trade.taker.TakerPaymentProtocolListener; import io.bitsquare.trade.payment.taker.TakerPaymentProtocolListener;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
@ -99,10 +99,10 @@ public class Trading
public void placeNewOffer(Offer offer, FutureCallback<Transaction> callback) throws InsufficientMoneyException public void placeNewOffer(Offer offer, FutureCallback<Transaction> callback) throws InsufficientMoneyException
{ {
if (myOffers.containsKey(offer.getUid())) if (myOffers.containsKey(offer.getUID()))
throw new IllegalStateException("offers contains already a offer with the ID " + offer.getUid()); throw new IllegalStateException("offers contains already a offer with the ID " + offer.getUID());
myOffers.put(offer.getUid(), offer); myOffers.put(offer.getUID(), offer);
//TODO for testing //TODO for testing
//storage.write(storageKey + ".offers", myOffers); //storage.write(storageKey + ".offers", myOffers);
walletFacade.payOfferFee(Fees.OFFER_CREATION_FEE, callback); walletFacade.payOfferFee(Fees.OFFER_CREATION_FEE, callback);
@ -110,17 +110,17 @@ public class Trading
public void removeOffer(Offer offer) throws IOException public void removeOffer(Offer offer) throws IOException
{ {
myOffers.remove(offer.getUid()); myOffers.remove(offer.getUID());
storage.write(storageKey + ".offers", myOffers); storage.write(storageKey + ".offers", myOffers);
} }
public Trade createTrade(Offer offer) public Trade createTrade(Offer offer)
{ {
if (trades.containsKey(offer.getUid())) if (trades.containsKey(offer.getUID()))
throw new IllegalStateException("trades contains already a trade with the ID " + offer.getUid()); throw new IllegalStateException("trades contains already a trade with the ID " + offer.getUID());
Trade trade = new Trade(offer); Trade trade = new Trade(offer);
trades.put(offer.getUid(), trade); trades.put(offer.getUID(), trade);
//TODO for testing //TODO for testing
//storage.write(storageKey + ".trades", trades); //storage.write(storageKey + ".trades", trades);

View file

@ -3,6 +3,8 @@ package io.bitsquare.trade.orderbook;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bitsquare.bank.BankAccount; import io.bitsquare.bank.BankAccount;
import io.bitsquare.gui.market.orderbook.OrderBookListItem; import io.bitsquare.gui.market.orderbook.OrderBookListItem;
import io.bitsquare.locale.Country;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.msg.MessageFacade; import io.bitsquare.msg.MessageFacade;
import io.bitsquare.msg.listeners.OrderBookListener; import io.bitsquare.msg.listeners.OrderBookListener;
import io.bitsquare.settings.Settings; import io.bitsquare.settings.Settings;
@ -72,7 +74,10 @@ public class OrderBook implements OrderBookListener
public void loadOffers() public void loadOffers()
{ {
messageFacade.getOffers(user.getCurrentBankAccount().getCurrency().getCurrencyCode()); if (user.getCurrentBankAccount() != null)
messageFacade.getOffers(user.getCurrentBankAccount().getCurrency().getCurrencyCode());
else
messageFacade.getOffers(CurrencyUtil.getDefaultCurrency().getCurrencyCode());
} }
public void removeOffer(Offer offer) throws IOException public void removeOffer(Offer offer) throws IOException
@ -101,7 +106,7 @@ public class OrderBook implements OrderBookListener
boolean currencyResult = currentBankAccount.getCurrency().equals(offer.getCurrency()); boolean currencyResult = currentBankAccount.getCurrency().equals(offer.getCurrency());
// The offer bank account country must match one of the accepted countries defined in the settings (1 to n) // The offer bank account country must match one of the accepted countries defined in the settings (1 to n)
boolean countryResult = countryInList(offer.getBankAccountCountryLocale(), settings.getAcceptedCountryLocales()); boolean countryResult = countryInList(offer.getBankAccountCountry(), settings.getAcceptedCountries());
// One of the supported languages from the settings must match one of the offer languages (n to n) // One of the supported languages from the settings must match one of the offer languages (n to n)
boolean languageResult = languagesInList(settings.getAcceptedLanguageLocales(), offer.getAcceptedLanguageLocales()); boolean languageResult = languagesInList(settings.getAcceptedLanguageLocales(), offer.getAcceptedLanguageLocales());
@ -151,7 +156,7 @@ public class OrderBook implements OrderBookListener
log.debug("currentBankAccount.getCurrency() = " + currentBankAccount.getCurrency() + log.debug("currentBankAccount.getCurrency() = " + currentBankAccount.getCurrency() +
", offer.getCurrency() = " + offer.getCurrency()); ", offer.getCurrency() = " + offer.getCurrency());
log.debug("offer.getCountryLocale() = " + offer.getBankAccountCountryLocale() + log.debug("offer.getCountryLocale() = " + offer.getBankAccountCountryLocale() +
", settings.getAcceptedCountryLocales() = " + settings.getAcceptedCountryLocales().toString()); ", settings.getAcceptedCountries() = " + settings.getAcceptedCountries().toString());
log.debug("settings.getAcceptedLanguageLocales() = " + settings.getAcceptedLanguageLocales() + log.debug("settings.getAcceptedLanguageLocales() = " + settings.getAcceptedLanguageLocales() +
", offer.getAcceptedLanguageLocales() = " + offer.getAcceptedLanguageLocales()); ", offer.getAcceptedLanguageLocales() = " + offer.getAcceptedLanguageLocales());
log.debug("currentBankAccount.getBankAccountType().getType() = " + currentBankAccount.getBankAccountType().getType() + log.debug("currentBankAccount.getBankAccountType().getType() = " + currentBankAccount.getBankAccountType().getType() +
@ -237,7 +242,7 @@ public class OrderBook implements OrderBookListener
@Override @Override
public boolean test(OrderBookListItem orderBookListItem) public boolean test(OrderBookListItem orderBookListItem)
{ {
return orderBookListItem.getOffer().getUid().equals(offer.getUid()); return orderBookListItem.getOffer().getUID().equals(offer.getUID());
} }
}); });
} }
@ -267,11 +272,11 @@ public class OrderBook implements OrderBookListener
// Private Methods // Private Methods
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
private boolean countryInList(Locale localeToMatch, List<Locale> list) private boolean countryInList(Country countryToMatch, List<Country> list)
{ {
for (Locale locale : list) for (Country country : list)
{ {
if (locale.getCountry().equals(localeToMatch.getCountry())) if (country.getCode().equals(countryToMatch.getCode()))
return true; return true;
} }
return false; return false;
@ -298,7 +303,7 @@ public class OrderBook implements OrderBookListener
{ {
try try
{ {
if (arbitrator.getUid().equals(arbitratorToMatch.getUid())) if (arbitrator.getUID().equals(arbitratorToMatch.getUID()))
return true; return true;
} catch (Exception e) } catch (Exception e)
{ {

View file

@ -1,4 +1,4 @@
package io.bitsquare.trade.offerer; package io.bitsquare.trade.payment.offerer;
import com.google.bitcoin.core.*; import com.google.bitcoin.core.*;
import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.FutureCallback;
@ -217,7 +217,7 @@ public class OffererPaymentProtocol
BigInteger offererInputAmount = trade.getCollateralAmount(); BigInteger offererInputAmount = trade.getCollateralAmount();
String offererPubKey = walletFacade.getPubKeyAsHex(); String offererPubKey = walletFacade.getPubKeyAsHex();
String takerPubKey = requestTradeMessage.getTakerMultiSigPubKey(); String takerPubKey = requestTradeMessage.getTakerMultiSigPubKey();
String arbitratorPubKey = offer.getArbitrator().getPubKey(); String arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
checkNotNull(requestTradeMessage.getTakerMultiSigPubKey()); checkNotNull(requestTradeMessage.getTakerMultiSigPubKey());
checkNotNull(offererPubKey); checkNotNull(offererPubKey);

View file

@ -1,4 +1,4 @@
package io.bitsquare.trade.offerer; package io.bitsquare.trade.payment.offerer;
import com.google.bitcoin.core.TransactionConfidence; import com.google.bitcoin.core.TransactionConfidence;

View file

@ -1,4 +1,4 @@
package io.bitsquare.trade.taker; package io.bitsquare.trade.payment.taker;
import com.google.bitcoin.core.AddressFormatException; import com.google.bitcoin.core.AddressFormatException;
import com.google.bitcoin.core.InsufficientMoneyException; import com.google.bitcoin.core.InsufficientMoneyException;
@ -29,7 +29,7 @@ import java.util.concurrent.ExecutionException;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
//TODO refactor to process based pattern //TODO use states
public class TakerPaymentProtocol public class TakerPaymentProtocol
{ {
private static final Logger log = LoggerFactory.getLogger(TakerPaymentProtocol.class); private static final Logger log = LoggerFactory.getLogger(TakerPaymentProtocol.class);
@ -77,6 +77,8 @@ public class TakerPaymentProtocol
{ {
log.debug("1 takeOffer"); log.debug("1 takeOffer");
findPeerAddress(); findPeerAddress();
} }
@ -368,7 +370,7 @@ public class TakerPaymentProtocol
String offererPubKey = requestTradeMessage.getOffererPubKey(); String offererPubKey = requestTradeMessage.getOffererPubKey();
String takerPubKey = walletFacade.getPubKeyAsHex(); String takerPubKey = walletFacade.getPubKeyAsHex();
String arbitratorPubKey = offer.getArbitrator().getPubKey(); String arbitratorPubKey = offer.getArbitrator().getPubKeyAsHex();
String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex(); String preparedOffererDepositTxAsHex = requestTradeMessage.getPreparedOffererDepositTxAsHex();
checkNotNull(takerInputAmount); checkNotNull(takerInputAmount);

View file

@ -1,4 +1,4 @@
package io.bitsquare.trade.taker; package io.bitsquare.trade.payment.taker;
import io.bitsquare.msg.TradeMessage; import io.bitsquare.msg.TradeMessage;

View file

@ -1,46 +1,154 @@
package io.bitsquare.user; package io.bitsquare.user;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigInteger; import java.util.List;
import java.util.Locale;
import java.util.Objects;
public class Arbitrator implements Serializable public class Arbitrator implements Serializable
{ {
private static final long serialVersionUID = -2625059604136756635L;
private String name;
private String pubKey;
private String messagePubKeyAsHex;
private String url;
private int baseFeePercent; // in percent int 1 for 1%
private int arbitrationFeePercent;
private BigInteger minArbitrationAmount; // in Satoshis
private String uid;
public Arbitrator(String uid, String name, String pubKey, String messagePubKeyAsHex, String url, int baseFeePercent, int arbitrationFeePercent, BigInteger minArbitrationAmount) public enum ID_TYPE
{ {
this.uid = uid; REAL_LIFE_ID,
this.name = name; NICKNAME,
this.pubKey = pubKey; COMPANY
this.messagePubKeyAsHex = messagePubKeyAsHex;
this.url = url;
this.baseFeePercent = baseFeePercent;
this.arbitrationFeePercent = arbitrationFeePercent;
this.minArbitrationAmount = minArbitrationAmount;
} }
public enum METHODS
{
TLS_NOTARY,
SKYPE_SCREEN_SHARING,
SMART_PHONE_VIDEO_CHAT,
REQUIRE_REAL_ID,
BANK_STATEMENT,
OTHER
}
public enum ID_VERIFICATIONS
{
PASSPORT,
GOV_ID,
UTILITY_BILLS,
FACEBOOK,
GOOGLE_PLUS,
TWITTER,
PGP,
BTC_OTC,
OTHER
}
private static final long serialVersionUID = -2625059604136756635L;
private String UID;
private String pubKeyAsHex;
private String messagePubKeyAsHex;
private String name;
private ID_TYPE idType;
private List<Locale> languages;
private Reputation reputation;
private double maxTradeVolume;
private double passiveServiceFee;
private double minPassiveServiceFee;
private double arbitrationFee;
private double minArbitrationFee;
private List<METHODS> arbitrationMethods;
private List<ID_VERIFICATIONS> idVerifications;
private String webUrl;
private String description;
public Arbitrator()
{
}
public Arbitrator(String pubKeyAsHex,
String messagePubKeyAsHex,
String name,
ID_TYPE idType,
List<Locale> languages,
Reputation reputation,
double maxTradeVolume,
double passiveServiceFee,
double minPassiveServiceFee,
double arbitrationFee,
double minArbitrationFee,
List<METHODS> arbitrationMethods,
List<ID_VERIFICATIONS> idVerifications,
String webUrl,
String description)
{
this.pubKeyAsHex = pubKeyAsHex;
this.messagePubKeyAsHex = messagePubKeyAsHex;
this.name = name;
this.idType = idType;
this.languages = languages;
this.reputation = reputation;
this.maxTradeVolume = maxTradeVolume;
this.passiveServiceFee = passiveServiceFee;
this.minPassiveServiceFee = minPassiveServiceFee;
this.arbitrationFee = arbitrationFee;
this.minArbitrationFee = minArbitrationFee;
this.arbitrationMethods = arbitrationMethods;
this.idVerifications = idVerifications;
this.webUrl = webUrl;
this.description = description;
//TODO use pubKeyAsHex
UID = name;
}
public void updateFromStorage(Arbitrator savedArbitrator)
{
this.pubKeyAsHex = savedArbitrator.getPubKeyAsHex();
this.messagePubKeyAsHex = savedArbitrator.getPubKeyAsHex();
this.name = savedArbitrator.getName();
this.idType = savedArbitrator.getIdType();
this.languages = savedArbitrator.getLanguages();
this.reputation = savedArbitrator.getReputation();
this.maxTradeVolume = savedArbitrator.getMaxTradeVolume();
this.passiveServiceFee = savedArbitrator.getPassiveServiceFee();
this.minPassiveServiceFee = savedArbitrator.getMinPassiveServiceFee();
this.arbitrationFee = savedArbitrator.getArbitrationFee();
this.minArbitrationFee = savedArbitrator.getMinArbitrationFee();
this.arbitrationMethods = savedArbitrator.getArbitrationMethods();
this.idVerifications = savedArbitrator.getIdVerifications();
this.webUrl = savedArbitrator.getWebUrl();
this.description = savedArbitrator.getDescription();
UID = pubKeyAsHex;
}
public int hashCode()
{
return Objects.hashCode(UID);
}
public boolean equals(Object obj)
{
if (!(obj instanceof Arbitrator))
return false;
if (obj == this)
return true;
Arbitrator other = (Arbitrator) obj;
return other.getUID().equals(UID);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Getters // Getters
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
public String getName() public String getUID()
{ {
return name; return UID;
} }
public String getPubKey() public String getPubKeyAsHex()
{ {
return pubKey; return pubKeyAsHex;
} }
public String getMessagePubKeyAsHex() public String getMessagePubKeyAsHex()
@ -48,43 +156,68 @@ public class Arbitrator implements Serializable
return messagePubKeyAsHex; return messagePubKeyAsHex;
} }
public String getUrl() public String getName()
{ {
return url; return name;
} }
public BigInteger getMinArbitrationAmount() public ID_TYPE getIdType()
{ {
return minArbitrationAmount; return idType;
} }
public int getBaseFeePercent() public List<Locale> getLanguages()
{ {
return baseFeePercent; return languages;
} }
public int getArbitrationFeePercent() public Reputation getReputation()
{ {
return arbitrationFeePercent; return reputation;
} }
public Object getUid() public double getMaxTradeVolume()
{ {
return uid; return maxTradeVolume;
} }
@Override public double getPassiveServiceFee()
public String toString()
{ {
return "Arbitrator{" + return passiveServiceFee;
"name='" + name + '\'' + }
", pubKey='" + pubKey + '\'' +
", messagePubKeyAsHex='" + messagePubKeyAsHex + '\'' + public double getMinPassiveServiceFee()
", url='" + url + '\'' + {
", baseFeePercent=" + baseFeePercent + return minPassiveServiceFee;
", arbitrationFeePercent=" + arbitrationFeePercent + }
", minArbitrationAmount=" + minArbitrationAmount +
", uid='" + uid + '\'' + public double getArbitrationFee()
'}'; {
return arbitrationFee;
}
public double getMinArbitrationFee()
{
return minArbitrationFee;
}
public List<METHODS> getArbitrationMethods()
{
return arbitrationMethods;
}
public List<ID_VERIFICATIONS> getIdVerifications()
{
return idVerifications;
}
public String getWebUrl()
{
return webUrl;
}
public String getDescription()
{
return description;
} }
} }

View file

@ -0,0 +1,26 @@
package io.bitsquare.user;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
public class Reputation implements Serializable
{
private static final long serialVersionUID = -3073174320050879490L;
private static final Logger log = LoggerFactory.getLogger(Reputation.class);
//TODO
public Reputation()
{
}
@Override
public String toString()
{
return "4 positive ratings in 5 cases";
}
}

View file

@ -43,10 +43,23 @@ public class User implements Serializable
public void addBankAccount(BankAccount bankAccount) public void addBankAccount(BankAccount bankAccount)
{ {
bankAccounts.add(bankAccount); if (!bankAccounts.contains(bankAccount))
bankAccounts.add(bankAccount);
currentBankAccount = bankAccount; currentBankAccount = bankAccount;
} }
public void removeCurrentBankAccount()
{
if (currentBankAccount != null)
bankAccounts.remove(currentBankAccount);
if (bankAccounts.size() > 0)
currentBankAccount = bankAccounts.get(0);
else
currentBankAccount = null;
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Setters // Setters
@ -86,13 +99,14 @@ public class User implements Serializable
public String getStringifiedBankAccounts() public String getStringifiedBankAccounts()
{ {
String bankAccountUIDs = ""; String bankAccountUIDs = "";
for (Iterator<BankAccount> iterator = getBankAccounts().iterator(); iterator.hasNext(); ) for (int i = 0; i < bankAccounts.size(); i++)
{ {
BankAccount bankAccount = iterator.next(); BankAccount bankAccount = bankAccounts.get(i);
bankAccountUIDs += bankAccount.toString(); bankAccountUIDs += bankAccount.toString();
if (iterator.hasNext()) if (i < bankAccounts.size() - 1)
bankAccountUIDs += ", "; bankAccountUIDs += ", ";
} }
return bankAccountUIDs; return bankAccountUIDs;
} }

View file

@ -1,122 +0,0 @@
package io.bitsquare.util;
import com.google.bitcoin.core.ECKey;
import io.bitsquare.bank.BankAccountType;
import io.bitsquare.user.Arbitrator;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PublicKey;
import java.util.*;
public class MockData
{
public static List<Currency> getCurrencies()
{
List<Currency> list = new ArrayList<>();
list.add(Currency.getInstance("EUR"));
list.add(Currency.getInstance("USD"));
list.add(Currency.getInstance("GBP"));
list.add(Currency.getInstance("RUB"));
list.add(Currency.getInstance("CAD"));
list.add(Currency.getInstance("AUD"));
list.add(Currency.getInstance("JPY"));
list.add(Currency.getInstance("CNY"));
list.add(Currency.getInstance("CHF"));
return list;
}
public static List<Currency> getRandomCurrencies()
{
return randomizeList(getCurrencies());
}
public static List<Locale> getLocales()
{
List<Locale> list = new ArrayList<>();
list.add(new Locale("de", "AT"));
list.add(new Locale("de", "DE"));
list.add(new Locale("en", "US"));
list.add(new Locale("en", "UK"));
list.add(new Locale("es", "ES"));
list.add(new Locale("ru", "RU"));
list.add(new Locale("zh", "CN"));
list.add(new Locale("en", "AU"));
list.add(new Locale("it", "IT"));
list.add(new Locale("en", "CA"));
return list;
}
public static List<Locale> getRandomLocales()
{
return randomizeList(getLocales());
}
public static List<Arbitrator> getArbitrators()
{
List<Arbitrator> list = new ArrayList<>();
list.add(new Arbitrator("uid_1", "Charlie Boom", com.google.bitcoin.core.Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Charly_Boom", 1, 10, com.google.bitcoin.core.Utils.toNanoCoins("0.01")));
list.add(new Arbitrator("uid_2", "Tom Shang", com.google.bitcoin.core.Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Tom_Shang", 0, 1, com.google.bitcoin.core.Utils.toNanoCoins("0.001")));
list.add(new Arbitrator("uid_3", "Edward Snow", com.google.bitcoin.core.Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Edward_Swow", 2, 5, com.google.bitcoin.core.Utils.toNanoCoins("0.05")));
list.add(new Arbitrator("uid_4", "Julian Sander", com.google.bitcoin.core.Utils.bytesToHexString(new ECKey().getPubKey()),
getMessagePubKey(), "http://www.arbit.io/Julian_Sander", 0, 20, com.google.bitcoin.core.Utils.toNanoCoins("0.1")));
return list;
}
private static String getMessagePubKey()
{
try
{
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");
keyGen.initialize(1024);
KeyPair generatedKeyPair = keyGen.genKeyPair();
PublicKey pubKey = generatedKeyPair.getPublic();
return DSAKeyUtil.getHexStringFromPublicKey(pubKey);
} catch (Exception e2)
{
return null;
}
}
public static List<Arbitrator> getRandomArbitrators()
{
return randomizeList(getArbitrators());
}
public static List<BankAccountType.BankAccountTypeEnum> getBankTransferTypeEnums()
{
return Utilities.getAllBankAccountTypeEnums();
}
public static List<BankAccountType.BankAccountTypeEnum> getRandomBankTransferTypeEnums()
{
return randomizeList(Utilities.getAllBankAccountTypeEnums());
}
public static List randomizeList(List list)
{
int e = new Random().nextInt(list.size());
if (list.size() > 0)
e = Math.max(e, 1);
int s = (e == 0) ? 0 : new Random().nextInt(e);
list = list.subList(s, e);
return list;
}
public static List reduce(List list, int count)
{
List result = new ArrayList();
for (int i = 0; i < count && i < list.size(); i++)
{
result.add(list.get(i));
}
return result;
}
}

View file

@ -4,7 +4,6 @@ import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.sun.xml.internal.messaging.saaj.util.ByteInputStream; import com.sun.xml.internal.messaging.saaj.util.ByteInputStream;
import io.bitsquare.bank.BankAccountType;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -12,10 +11,7 @@ import org.slf4j.LoggerFactory;
import java.awt.*; import java.awt.*;
import java.io.*; import java.io.*;
import java.net.URI; import java.net.URI;
import java.util.*;
import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate;
public class Utilities public class Utilities
{ {
@ -136,97 +132,19 @@ public class Utilities
return obj; return obj;
} }
public static ArrayList<Locale> getAllLocales()
/* public static ArrayList<BankAccountTypeInfo.BankAccountType> getAllBankAccountTypeEnums()
{ {
ArrayList<Locale> list = new ArrayList<Locale>(Arrays.asList(Locale.getAvailableLocales())); ArrayList<BankAccountTypeInfo.BankAccountType> bankAccountTypes = new ArrayList<>();
list.removeIf(new Predicate<Locale>() bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.SEPA);
{ bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.WIRE);
@Override bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.INTERNATIONAL);
public boolean test(Locale locale) bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.OK_PAY);
{ bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.NET_TELLER);
return locale == null || locale.getCountry().equals("") || locale.getLanguage().equals(""); bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.PERFECT_MONEY);
} bankAccountTypes.add(BankAccountTypeInfo.BankAccountType.OTHER);
}); return bankAccountTypes;
} */
list.sort(new Comparator<Locale>()
{
@Override
public int compare(Locale locale1, Locale locale2)
{
return locale1.getDisplayCountry().compareTo(locale2.getDisplayCountry());
}
});
Locale defaultLocale = Locale.getDefault();
//Locale defaultLocale = new Locale("de", "AT");
list.remove(defaultLocale);
list.add(0, defaultLocale);
return list;
}
public static List<Currency> getAllCurrencies()
{
ArrayList<Currency> mainCurrencies = new ArrayList<>();
mainCurrencies.add(Currency.getInstance("USD"));
mainCurrencies.add(Currency.getInstance("EUR"));
mainCurrencies.add(Currency.getInstance("CNY"));
mainCurrencies.add(Currency.getInstance("RUB"));
mainCurrencies.add(Currency.getInstance("JPY"));
mainCurrencies.add(Currency.getInstance("GBP"));
mainCurrencies.add(Currency.getInstance("CAD"));
mainCurrencies.add(Currency.getInstance("AUD"));
mainCurrencies.add(Currency.getInstance("CHF"));
mainCurrencies.add(Currency.getInstance("CNY"));
Set<Currency> allCurrenciesSet = Currency.getAvailableCurrencies();
allCurrenciesSet.removeAll(mainCurrencies);
List<Currency> allCurrenciesList = new ArrayList<>(allCurrenciesSet);
allCurrenciesList.sort(new Comparator<Currency>()
{
@Override
public int compare(Currency a, Currency b)
{
return a.getCurrencyCode().compareTo(b.getCurrencyCode());
}
});
List<Currency> resultList = new ArrayList<>(mainCurrencies);
resultList.addAll(allCurrenciesList);
Currency defaultCurrency = Currency.getInstance(Locale.getDefault());
resultList.remove(defaultCurrency);
resultList.add(0, defaultCurrency);
return resultList;
}
public static ArrayList<BankAccountType.BankAccountTypeEnum> getAllBankAccountTypeEnums()
{
ArrayList<BankAccountType.BankAccountTypeEnum> bankAccountTypeEnums = new ArrayList<>();
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.SEPA);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.WIRE);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.INTERNATIONAL);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.OK_PAY);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.NET_TELLER);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.PERFECT_MONEY);
bankAccountTypeEnums.add(BankAccountType.BankAccountTypeEnum.OTHER);
return bankAccountTypeEnums;
}
public static ArrayList<BankAccountType> getAllBankAccountTypes()
{
ArrayList<BankAccountType> bankTransferTypes = new ArrayList<>();
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.SEPA, "IBAN", "BIC"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.WIRE, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.INTERNATIONAL, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.OK_PAY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.NET_TELLER, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.PERFECT_MONEY, "Prim_todo", "Sec_todo"));
bankTransferTypes.add(new BankAccountType(BankAccountType.BankAccountTypeEnum.OTHER, "Prim_todo", "Sec_todo"));
return bankTransferTypes;
}
public static AnimationTimer setTimeout(int delay, Function<AnimationTimer, Void> callback) public static AnimationTimer setTimeout(int delay, Function<AnimationTimer, Void> callback)
{ {

View file

@ -1,8 +1,35 @@
currency=Währung
# generic
OTHER=Other
# BankAccountTypeInfo.BankAccountType
SEPA=Sepa SEPA=Sepa
WIRE=Wire WIRE=Wire
INTERNATIONAL=International INTERNATIONAL=International
OK_PAY=OK Pay OK_PAY=OK Pay
NET_TELLER=Netteller NET_TELLER=Netteller
PERFECT_MONEY=Perfect Money PERFECT_MONEY=Perfect Money
OTHER=Other
# Arbitrator.ID_TYPE
REAL_LIFE_ID=Real life ID
NICKNAME=Nickname
COMPANY=Company
# Arbitrator.METHODS
TLS_NOTARY=TLS Notary
SKYPE_SCREEN_SHARING=Skype screen sharing
SMART_PHONE_VIDEO_CHAT=Smart phone video chat
REQUIRE_REAL_ID=Require real life Identification
BANK_STATEMENT=Bank statement
# Arbitrator.ID_VERIFICATIONS
PASSPORT=Passport
GOV_ID=Government issued ID
UTILITY_BILLS=Utility bills
FACEBOOK=Facebook account
GOOGLE_PLUS=Google+ account
TWITTER=Twitter account
PGP=PGP
BTC_OTC=BTC OTC

View file

@ -1,8 +1,35 @@
currency=Currency
# generic
OTHER=Other
# BankAccountTypeInfo.BankAccountType
SEPA=Sepa SEPA=Sepa
WIRE=Wire WIRE=Wire
INTERNATIONAL=International INTERNATIONAL=International
OK_PAY=OK Pay OK_PAY=OK Pay
NET_TELLER=Netteller NET_TELLER=Netteller
PERFECT_MONEY=Perfect Money PERFECT_MONEY=Perfect Money
OTHER=Other
# Arbitrator.ID_TYPE
REAL_LIFE_ID=Real life ID
NICKNAME=Nickname
COMPANY=Company
# Arbitrator.METHODS
TLS_NOTARY=TLS Notary
SKYPE_SCREEN_SHARING=Skype screen sharing
SMART_PHONE_VIDEO_CHAT=Smart phone video chat
REQUIRE_REAL_ID=Require real life Identification
BANK_STATEMENT=Bank statement
# Arbitrator.ID_VERIFICATIONS
PASSPORT=Passport
GOV_ID=Government issued ID
UTILITY_BILLS=Utility bills
FACEBOOK=Facebook account
GOOGLE_PLUS=Google+ account
TWITTER=Twitter account
PGP=PGP
BTC_OTC=BTC OTC

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

View file

@ -0,0 +1,29 @@
package io.bitsquare.gui.util;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class BitSquareConverterTest
{
@Test
public void testStringToDouble()
{
assertEquals(1, BitSquareConverter.stringToDouble("1"), 0);
assertEquals(0.1, BitSquareConverter.stringToDouble("0.1"), 0);
assertEquals(0.1, BitSquareConverter.stringToDouble("0,1"), 0);
assertEquals(1, BitSquareConverter.stringToDouble("1.0"), 0);
assertEquals(1, BitSquareConverter.stringToDouble("1,0"), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("1,000.2"), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(null), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(""), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("."), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble(","), 0);
assertEquals(Double.NEGATIVE_INFINITY, BitSquareConverter.stringToDouble("a"), 0);
}
}

View file

@ -0,0 +1,36 @@
package io.bitsquare.gui.util;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class BitSquareValidatorTest
{
@Test
public void testValidateStringAsDouble()
{
assertTrue(BitSquareValidator.validateStringAsDouble("0"));
assertTrue(BitSquareValidator.validateStringAsDouble("1"));
assertTrue(BitSquareValidator.validateStringAsDouble("0,1"));
assertTrue(BitSquareValidator.validateStringAsDouble("0.01"));
assertFalse(BitSquareValidator.validateStringAsDouble(""));
assertFalse(BitSquareValidator.validateStringAsDouble("a"));
assertFalse(BitSquareValidator.validateStringAsDouble("0.0.1"));
assertFalse(BitSquareValidator.validateStringAsDouble("1,000.1"));
assertFalse(BitSquareValidator.validateStringAsDouble("1.000,1"));
assertFalse(BitSquareValidator.validateStringAsDouble(null));
}
@Test
public void testValidateStringNotEmpty()
{
assertTrue(BitSquareValidator.validateStringNotEmpty("a"));
assertTrue(BitSquareValidator.validateStringNotEmpty("123"));
assertFalse(BitSquareValidator.validateStringNotEmpty(""));
assertFalse(BitSquareValidator.validateStringNotEmpty(" "));
assertFalse(BitSquareValidator.validateStringNotEmpty(null));
}
}

View file

@ -1,16 +0,0 @@
package io.bitsquare.gui.util;
import io.bitsquare.bank.BankAccountType;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class VerificationTest
{
@Test
public void testVerifyBankAccountData()
{
// TODO define rules for prim. and sec. ID per bank account type
assertTrue(Verification.verifyAccountIDsByBankTransferType(BankAccountType.BankAccountTypeEnum.SEPA, "DE11876543210000123456", "12345678"));
}
}

View file

@ -0,0 +1,19 @@
package io.bitsquare.util;
import io.bitsquare.locale.CountryUtil;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class LocationUtilsTest
{
@Test
public void testVerifyBankAccountData()
{
CountryUtil.getAllCountries();
assertTrue(true);
//assertTrue(Verification.verifyAccountIDsByBankTransferType(BankAccountType.BankAccountTypeEnum.SEPA, "DE11876543210000123456", "12345678"));
}
}