mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 23:18:17 +01:00
Merge branch 'Development'
This commit is contained in:
commit
ef46e50798
136 changed files with 1089 additions and 758 deletions
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ public class Version {
|
|||
private static final Logger log = LoggerFactory.getLogger(Version.class);
|
||||
|
||||
// The application versions
|
||||
public static final String VERSION = "0.4.9.1";
|
||||
public static final String VERSION = "0.4.9.2";
|
||||
|
||||
// The version nr. for the objects sent over the network. A change will break the serialization of old objects.
|
||||
// If objects are used for both network and database the network version is applied.
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.security.interfaces.DSAParams;
|
|||
import java.security.interfaces.DSAPrivateKey;
|
||||
import java.security.interfaces.RSAPrivateCrtKey;
|
||||
import java.security.spec.*;
|
||||
import java.util.Date;
|
||||
|
||||
// TODO: use a password protection for key storage
|
||||
public class KeyStorage {
|
||||
|
@ -124,7 +125,7 @@ public class KeyStorage {
|
|||
throw new RuntimeException("Unsupported key algo" + keyEntry.getAlgorithm());
|
||||
}
|
||||
|
||||
//log.info("load completed in {} msec", System.currentTimeMillis() - now);
|
||||
log.debug("load completed in {} msec", System.currentTimeMillis() - new Date().getTime());
|
||||
return new KeyPair(publicKey, privateKey);
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchProviderException e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -24,12 +24,11 @@ public class Profiler {
|
|||
private static final Logger log = LoggerFactory.getLogger(Profiler.class);
|
||||
|
||||
public static void printSystemLoad(Logger log) {
|
||||
log.warn(printSystemLoadString());
|
||||
log.info(printSystemLoadString());
|
||||
}
|
||||
|
||||
public static String printSystemLoadString() {
|
||||
long used = getUsedMemoryInMB();
|
||||
return "System load: Memory (MB)): " + used + " / Nr. of threads: " + Thread.activeCount();
|
||||
return "System load: Memory (MB)): " + getUsedMemoryInMB() + " / Nr. of threads: " + Thread.activeCount();
|
||||
}
|
||||
|
||||
public static long getUsedMemoryInMB() {
|
||||
|
|
|
@ -33,9 +33,7 @@ import java.awt.*;
|
|||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.Permission;
|
||||
import java.security.PermissionCollection;
|
||||
import java.util.Locale;
|
||||
|
@ -207,26 +205,6 @@ public class Utilities {
|
|||
}
|
||||
}
|
||||
|
||||
public static void openWebPage(String target) {
|
||||
try {
|
||||
openURI(new URI(target));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void openMail(String to, String subject, String body) {
|
||||
try {
|
||||
subject = URLEncoder.encode(subject, "UTF-8").replace("+", "%20");
|
||||
body = URLEncoder.encode(body, "UTF-8").replace("+", "%20");
|
||||
openURI(new URI("mailto:" + to + "?subject=" + subject + "&body=" + body));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
log.error("openMail failed " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void printSystemLoad() {
|
||||
Runtime runtime = Runtime.getRuntime();
|
||||
long free = runtime.freeMemory() / 1024 / 1024;
|
||||
|
|
|
@ -197,12 +197,12 @@ public class FileManager<T> {
|
|||
|
||||
renameTempFileToFile(tempFile, storageFile);
|
||||
} catch (Throwable t) {
|
||||
log.debug("storageFile " + storageFile.toString());
|
||||
log.error("storageFile " + storageFile.toString());
|
||||
t.printStackTrace();
|
||||
log.error("Error at saveToFile: " + t.getMessage());
|
||||
} finally {
|
||||
if (tempFile != null && tempFile.exists()) {
|
||||
log.warn("Temp file still exists after failed save. storageFile=" + storageFile);
|
||||
log.warn("Temp file still exists after failed save. We will delete it now. storageFile=" + storageFile);
|
||||
if (!tempFile.delete())
|
||||
log.error("Cannot delete temp file.");
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>core</artifactId>
|
||||
|
|
|
@ -62,7 +62,7 @@ public class BitsquareEnvironment extends StandardEnvironment {
|
|||
public static final String DEFAULT_USER_DATA_DIR = defaultUserDataDir();
|
||||
public static final String DEFAULT_APP_DATA_DIR = appDataDir(DEFAULT_USER_DATA_DIR, DEFAULT_APP_NAME);
|
||||
|
||||
public static final String LOG_LEVEL_DEFAULT = (DevFlags.STRESS_TEST_MODE || DevFlags.DEV_MODE) ? Level.TRACE.levelStr : Level.WARN.levelStr;
|
||||
public static final String LOG_LEVEL_DEFAULT = (DevFlags.STRESS_TEST_MODE || DevFlags.DEV_MODE) ? Level.TRACE.levelStr : Level.INFO.levelStr;
|
||||
|
||||
static final String BITSQUARE_COMMANDLINE_PROPERTY_SOURCE_NAME = "bitsquareCommandLineProperties";
|
||||
static final String BITSQUARE_APP_DIR_PROPERTY_SOURCE_NAME = "bitsquareAppDirProperties";
|
||||
|
|
|
@ -159,19 +159,26 @@ public final class Dispute implements Payload {
|
|||
}
|
||||
|
||||
public void setIsClosed(boolean isClosed) {
|
||||
boolean changed = this.isClosed != isClosed;
|
||||
this.isClosed = isClosed;
|
||||
isClosedProperty.set(isClosed);
|
||||
storage.queueUpForSave();
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void setDisputeResult(DisputeResult disputeResult) {
|
||||
boolean changed = this.disputeResult == null || !this.disputeResult.equals(disputeResult);
|
||||
this.disputeResult = disputeResult;
|
||||
disputeResultProperty.set(disputeResult);
|
||||
storage.queueUpForSave();
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void setDisputePayoutTxId(String disputePayoutTxId) {
|
||||
boolean changed = this.disputePayoutTxId == null || !this.disputePayoutTxId.equals(disputePayoutTxId);
|
||||
this.disputePayoutTxId = disputePayoutTxId;
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -60,10 +60,11 @@ public final class DisputeList<DisputeCase> extends ArrayList<DisputeCase> imple
|
|||
@Override
|
||||
public boolean add(DisputeCase disputeCase) {
|
||||
if (!super.contains(disputeCase)) {
|
||||
boolean result = super.add(disputeCase);
|
||||
boolean changed = super.add(disputeCase);
|
||||
getObservableList().add(disputeCase);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
return changed;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -71,10 +72,11 @@ public final class DisputeList<DisputeCase> extends ArrayList<DisputeCase> imple
|
|||
|
||||
@Override
|
||||
public boolean remove(Object disputeCase) {
|
||||
boolean result = super.remove(disputeCase);
|
||||
boolean changed = super.remove(disputeCase);
|
||||
getObservableList().remove(disputeCase);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
return changed;
|
||||
}
|
||||
|
||||
private ObservableList<DisputeCase> getObservableList() {
|
||||
|
|
|
@ -68,8 +68,9 @@ public final class AddressEntryList extends ArrayList<AddressEntry> implements P
|
|||
}
|
||||
|
||||
public AddressEntry addAddressEntry(AddressEntry addressEntry) {
|
||||
add(addressEntry);
|
||||
storage.queueUpForSave();
|
||||
boolean changed = add(addressEntry);
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
return addressEntry;
|
||||
}
|
||||
|
||||
|
@ -78,17 +79,19 @@ public final class AddressEntryList extends ArrayList<AddressEntry> implements P
|
|||
Optional<AddressEntry> addressEntryOptional = this.stream().filter(addressEntry -> offerId.equals(addressEntry.getOfferId())).findAny();
|
||||
if (addressEntryOptional.isPresent()) {
|
||||
AddressEntry addressEntry = addressEntryOptional.get();
|
||||
add(new AddressEntry(addressEntry.getKeyPair(), wallet.getParams(), AddressEntry.Context.AVAILABLE));
|
||||
remove(addressEntry);
|
||||
storage.queueUpForSave();
|
||||
boolean changed1 = add(new AddressEntry(addressEntry.getKeyPair(), wallet.getParams(), AddressEntry.Context.AVAILABLE));
|
||||
boolean changed2 = remove(addressEntry);
|
||||
if (changed1 || changed2)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
}
|
||||
|
||||
public void swapToAvailable(AddressEntry addressEntry) {
|
||||
remove(addressEntry);
|
||||
add(new AddressEntry(addressEntry.getKeyPair(), wallet.getParams(), AddressEntry.Context.AVAILABLE));
|
||||
remove(addressEntry);
|
||||
storage.queueUpForSave();
|
||||
boolean changed1 = add(new AddressEntry(addressEntry.getKeyPair(), wallet.getParams(), AddressEntry.Context.AVAILABLE));
|
||||
boolean changed2 = remove(addressEntry);
|
||||
if (changed1 || changed2)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void queueUpForSave() {
|
||||
|
|
|
@ -145,7 +145,7 @@ public class SeedPeersSocks5Dns implements PeerDiscovery {
|
|||
InetAddress addrResolved = proxySocket.getInetAddress();
|
||||
proxySocket.close();
|
||||
if( addrResolved != null ) {
|
||||
log.info("Resolved " + addr.getHostString() + " to " + addrResolved.getHostAddress() );
|
||||
log.debug("Resolved " + addr.getHostString() + " to " + addrResolved.getHostAddress());
|
||||
return new InetSocketAddress(addrResolved, addr.getPort() );
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -981,7 +981,7 @@ public class TradeWalletService {
|
|||
transaction.addOutput(buyerPayoutAmount, new Address(params, buyerAddressString));
|
||||
transaction.addOutput(sellerPayoutAmount, new Address(params, sellerAddressString));
|
||||
if (lockTime != 0) {
|
||||
log.info("We use a lockTime of " + lockTime);
|
||||
log.debug("We use a lockTime of " + lockTime);
|
||||
// When using lockTime we need to set sequenceNumber to 0
|
||||
transaction.getInputs().stream().forEach(i -> i.setSequenceNumber(0));
|
||||
transaction.setLockTime(lockTime);
|
||||
|
|
|
@ -170,7 +170,7 @@ public class WalletService {
|
|||
backupWallet();
|
||||
|
||||
final Socks5Proxy socks5Proxy = preferences.getUseTorForBitcoinJ() ? socks5ProxyProvider.getSocks5Proxy() : null;
|
||||
log.info("Use socks5Proxy for bitcoinj: " + socks5Proxy);
|
||||
log.debug("Use socks5Proxy for bitcoinj: " + socks5Proxy);
|
||||
|
||||
// If seed is non-null it means we are restoring from backup.
|
||||
walletAppKit = new WalletAppKitBitSquare(params, socks5Proxy, walletDir, "Bitsquare") {
|
||||
|
@ -714,7 +714,7 @@ public class WalletService {
|
|||
public void doubleSpendTransaction(Transaction txToDoubleSpend, Address toAddress, Runnable resultHandler, ErrorMessageHandler errorMessageHandler) throws InsufficientMoneyException, AddressFormatException, AddressEntryException {
|
||||
final TransactionConfidence.ConfidenceType confidenceType = txToDoubleSpend.getConfidence().getConfidenceType();
|
||||
if (confidenceType == TransactionConfidence.ConfidenceType.PENDING) {
|
||||
log.info("txToDoubleSpend nr. of inputs " + txToDoubleSpend.getInputs().size());
|
||||
log.debug("txToDoubleSpend nr. of inputs " + txToDoubleSpend.getInputs().size());
|
||||
|
||||
Transaction newTransaction = new Transaction(params);
|
||||
txToDoubleSpend.getInputs().stream().forEach(input -> {
|
||||
|
@ -739,8 +739,8 @@ public class WalletService {
|
|||
}
|
||||
);
|
||||
|
||||
log.info("newTransaction nr. of inputs " + newTransaction.getInputs().size());
|
||||
log.info("newTransaction size in kB " + newTransaction.bitcoinSerialize().length / 1024);
|
||||
log.debug("newTransaction nr. of inputs " + newTransaction.getInputs().size());
|
||||
log.debug("newTransaction size in kB " + newTransaction.bitcoinSerialize().length / 1024);
|
||||
|
||||
if (!newTransaction.getInputs().isEmpty()) {
|
||||
Coin amount = Coin.valueOf(newTransaction.getInputs().stream()
|
||||
|
@ -795,7 +795,7 @@ public class WalletService {
|
|||
}
|
||||
}
|
||||
if (sendResult != null) {
|
||||
log.info("Broadcasting double spending transaction. " + newTransaction);
|
||||
log.debug("Broadcasting double spending transaction. " + newTransaction);
|
||||
Futures.addCallback(sendResult.broadcastComplete, new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction result) {
|
||||
|
@ -835,9 +835,9 @@ public class WalletService {
|
|||
newSendRequest.feePerKb = FeePolicy.getNonTradeFeePerKb();
|
||||
wallet.completeTx(newSendRequest);
|
||||
|
||||
log.info("After fee check: amount " + amount.toFriendlyString());
|
||||
log.info("Output fee " + sendRequest.tx.getFee().toFriendlyString());
|
||||
sendRequest.tx.getOutputs().stream().forEach(o -> log.info("Output value " + o.getValue().toFriendlyString()));
|
||||
log.debug("After fee check: amount " + amount.toFriendlyString());
|
||||
log.debug("Output fee " + sendRequest.tx.getFee().toFriendlyString());
|
||||
sendRequest.tx.getOutputs().stream().forEach(o -> log.debug("Output value " + o.getValue().toFriendlyString()));
|
||||
} catch (InsufficientMoneyException e) {
|
||||
if (e.missing != null) {
|
||||
log.trace("missing fee " + e.missing.toFriendlyString());
|
||||
|
|
|
@ -38,7 +38,7 @@ public class BlockchainService {
|
|||
Futures.addCallback(future, new FutureCallback<Coin>() {
|
||||
public void onSuccess(Coin fee) {
|
||||
if (!resultFuture.isDone()) {
|
||||
log.info("Request fee from providers done after {} ms.", (System.currentTimeMillis() - startTime));
|
||||
log.debug("Request fee from providers done after {} ms.", (System.currentTimeMillis() - startTime));
|
||||
resultFuture.set(fee);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class GetFeeRequest {
|
|||
try {
|
||||
return provider.getFee(transactionId);
|
||||
} catch (IOException | HttpException e) {
|
||||
log.info("Fee request failed for tx {} from provider {}\n" +
|
||||
log.debug("Fee request failed for tx {} from provider {}\n" +
|
||||
"That is expected if the tx was not propagated yet to the provider.\n" +
|
||||
"error={}",
|
||||
transactionId, provider, e.getMessage());
|
||||
|
@ -43,7 +43,7 @@ class GetFeeRequest {
|
|||
|
||||
Futures.addCallback(future, new FutureCallback<Coin>() {
|
||||
public void onSuccess(Coin fee) {
|
||||
log.info("Received fee of {}\nfor tx {}\nfrom provider {}", fee.toFriendlyString(), transactionId, provider);
|
||||
log.debug("Received fee of {}\nfor tx {}\nfrom provider {}", fee.toFriendlyString(), transactionId, provider);
|
||||
resultFuture.set(fee);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ class GetPriceRequest {
|
|||
}
|
||||
|
||||
public void onFailure(@NotNull Throwable throwable) {
|
||||
log.error("requestPrice.onFailure: throwable=" + throwable.toString());
|
||||
resultFuture.setException(throwable);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ public class PriceFeedService {
|
|||
}
|
||||
}
|
||||
|
||||
private static final long PERIOD_FIAT_SEC = new Random().nextInt(5) + 90;
|
||||
private static final long PERIOD_FIAT_SEC = new Random().nextInt(5) + 70;
|
||||
private static final long PERIOD_ALL_FIAT_SEC = new Random().nextInt(5) + 180;
|
||||
private static final long PERIOD_ALL_CRYPTO_SEC = new Random().nextInt(5) + 180;
|
||||
|
||||
|
@ -63,8 +63,7 @@ public class PriceFeedService {
|
|||
private long bitcoinAveragePriceProviderLastCallAllTs;
|
||||
private long poloniexPriceProviderLastCallAllTs;
|
||||
private long bitcoinAveragePriceProviderLastCallTs;
|
||||
private Timer cryptoCurrenciesTime;
|
||||
private Timer fiatCurrenciesTime;
|
||||
private Timer requestFiatPriceTimer;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -86,20 +85,11 @@ public class PriceFeedService {
|
|||
this.priceConsumer = resultHandler;
|
||||
this.faultHandler = faultHandler;
|
||||
|
||||
requestAllPrices(fiatPriceProvider, () -> {
|
||||
applyPrice();
|
||||
if (fiatCurrenciesTime == null)
|
||||
fiatCurrenciesTime = UserThread.runPeriodically(() -> requestPrice(fiatPriceProvider), PERIOD_FIAT_SEC);
|
||||
});
|
||||
requestAllPrices(fiatPriceProvider, () -> applyPriceToConsumer());
|
||||
UserThread.runPeriodically(() -> requestAllPrices(fiatPriceProvider, this::applyPriceToConsumer), PERIOD_ALL_FIAT_SEC);
|
||||
|
||||
requestAllPrices(cryptoCurrenciesPriceProvider, () -> {
|
||||
applyPrice();
|
||||
if (cryptoCurrenciesTime == null)
|
||||
cryptoCurrenciesTime = UserThread.runPeriodically(() -> requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice),
|
||||
PERIOD_ALL_CRYPTO_SEC);
|
||||
});
|
||||
|
||||
UserThread.runPeriodically(() -> requestAllPrices(fiatPriceProvider, this::applyPrice), PERIOD_ALL_FIAT_SEC);
|
||||
requestAllPrices(cryptoCurrenciesPriceProvider, () -> applyPriceToConsumer());
|
||||
UserThread.runPeriodically(() -> requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPriceToConsumer), PERIOD_ALL_CRYPTO_SEC);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -110,7 +100,6 @@ public class PriceFeedService {
|
|||
return null;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -118,19 +107,21 @@ public class PriceFeedService {
|
|||
public void setType(Type type) {
|
||||
this.type = type;
|
||||
typeProperty.set(type);
|
||||
applyPrice();
|
||||
applyPriceToConsumer();
|
||||
}
|
||||
|
||||
public void setCurrencyCode(String currencyCode) {
|
||||
if (this.currencyCode == null || !this.currencyCode.equals(currencyCode)) {
|
||||
this.currencyCode = currencyCode;
|
||||
currencyCodeProperty.set(currencyCode);
|
||||
applyPrice();
|
||||
applyPriceToConsumer();
|
||||
|
||||
if (CurrencyUtil.isCryptoCurrency(currencyCode)) {
|
||||
stopRequestFiatPriceTimer();
|
||||
// Poloniex does not support calls for one currency just for all which is quite a bit of data
|
||||
requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice);
|
||||
requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPriceToConsumer);
|
||||
} else {
|
||||
startRequestFiatPriceTimer();
|
||||
requestPrice(fiatPriceProvider);
|
||||
}
|
||||
}
|
||||
|
@ -166,12 +157,27 @@ public class PriceFeedService {
|
|||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void applyPrice() {
|
||||
|
||||
private void startRequestFiatPriceTimer() {
|
||||
stopRequestFiatPriceTimer();
|
||||
requestFiatPriceTimer = UserThread.runPeriodically(() -> requestPrice(fiatPriceProvider), PERIOD_FIAT_SEC);
|
||||
}
|
||||
|
||||
private void stopRequestFiatPriceTimer() {
|
||||
if (requestFiatPriceTimer != null)
|
||||
requestFiatPriceTimer.stop();
|
||||
}
|
||||
|
||||
private void applyPriceToConsumer() {
|
||||
if (priceConsumer != null && currencyCode != null && type != null) {
|
||||
if (cache.containsKey(currencyCode)) {
|
||||
MarketPrice marketPrice = cache.get(currencyCode);
|
||||
if (marketPrice != null)
|
||||
try {
|
||||
MarketPrice marketPrice = cache.get(currencyCode);
|
||||
priceConsumer.accept(marketPrice.getPrice(type));
|
||||
} catch (Throwable t) {
|
||||
log.warn("Error at applyPriceToConsumer " + t.getMessage());
|
||||
}
|
||||
|
||||
} else {
|
||||
String errorMessage = "We don't have a price for currencyCode " + currencyCode;
|
||||
log.debug(errorMessage);
|
||||
|
@ -192,21 +198,25 @@ public class PriceFeedService {
|
|||
|
||||
if (allowed) {
|
||||
GetPriceRequest getPriceRequest = new GetPriceRequest();
|
||||
SettableFuture<MarketPrice> future = getPriceRequest.requestPrice(currencyCode, provider);
|
||||
Futures.addCallback(future, new FutureCallback<MarketPrice>() {
|
||||
public void onSuccess(MarketPrice marketPrice) {
|
||||
UserThread.execute(() -> {
|
||||
if (marketPrice != null && priceConsumer != null) {
|
||||
cache.put(marketPrice.currencyCode, marketPrice);
|
||||
priceConsumer.accept(marketPrice.getPrice(type));
|
||||
}
|
||||
});
|
||||
}
|
||||
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||
SettableFuture<MarketPrice> future = getPriceRequest.requestPrice(currencyCode, provider);
|
||||
Futures.addCallback(future, new FutureCallback<MarketPrice>() {
|
||||
public void onSuccess(MarketPrice marketPrice) {
|
||||
UserThread.execute(() -> {
|
||||
if (marketPrice != null && priceConsumer != null) {
|
||||
cache.put(marketPrice.currencyCode, marketPrice);
|
||||
priceConsumer.accept(marketPrice.getPrice(type));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void onFailure(@NotNull Throwable throwable) {
|
||||
log.debug("Could not load marketPrice\n" + throwable.getMessage());
|
||||
}
|
||||
});
|
||||
public void onFailure(@NotNull Throwable throwable) {
|
||||
log.debug("Could not load marketPrice\n" + throwable.getMessage());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.warn("We tried to call requestPrice with a non fiat currency selected: selectedCurrencyCode=" + currencyCode);
|
||||
}
|
||||
} else {
|
||||
log.debug("Ignore request. Too many attempt to call the API provider " + provider);
|
||||
}
|
||||
|
|
|
@ -30,11 +30,11 @@ public class ScryptUtil {
|
|||
public static void deriveKeyWithScrypt(KeyCrypterScrypt keyCrypterScrypt, String password, DeriveKeyResultHandler resultHandler) {
|
||||
Utilities.getThreadPoolExecutor("ScryptUtil:deriveKeyWithScrypt-%d", 1, 2, 5L).submit(() -> {
|
||||
try {
|
||||
log.info("Doing key derivation");
|
||||
log.debug("Doing key derivation");
|
||||
long start = System.currentTimeMillis();
|
||||
KeyParameter aesKey = keyCrypterScrypt.deriveKey(password);
|
||||
long duration = System.currentTimeMillis() - start;
|
||||
log.info("Key derivation took {} msec", duration);
|
||||
log.debug("Key derivation took {} msec", duration);
|
||||
UserThread.execute(() -> {
|
||||
try {
|
||||
resultHandler.handleResult(aesKey);
|
||||
|
|
32
core/src/main/java/io/bitsquare/locale/CurrencyTuple.java
Normal file
32
core/src/main/java/io/bitsquare/locale/CurrencyTuple.java
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* This file is part of Bitsquare.
|
||||
*
|
||||
* Bitsquare is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bitsquare 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 Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.locale;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class CurrencyTuple implements Serializable {
|
||||
// That object is used for serializing to a Json file.
|
||||
|
||||
public final String code;
|
||||
public final String name;
|
||||
|
||||
public CurrencyTuple(String code, String name) {
|
||||
this.code = code;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -65,18 +65,20 @@ public final class TradableList<T extends Tradable> extends ArrayList<T> impleme
|
|||
|
||||
@Override
|
||||
public boolean add(T tradable) {
|
||||
boolean result = super.add(tradable);
|
||||
boolean changed = super.add(tradable);
|
||||
getObservableList().add(tradable);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object tradable) {
|
||||
boolean result = super.remove(tradable);
|
||||
boolean changed = super.remove(tradable);
|
||||
getObservableList().remove(tradable);
|
||||
storage.queueUpForSave();
|
||||
return result;
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
return changed;
|
||||
}
|
||||
|
||||
public ObservableList<T> getObservableList() {
|
||||
|
|
|
@ -316,16 +316,20 @@ public abstract class Trade implements Tradable, Model {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void setState(State state) {
|
||||
boolean changed = this.state != state;
|
||||
this.state = state;
|
||||
stateProperty.set(state);
|
||||
persist();
|
||||
if (changed)
|
||||
persist();
|
||||
}
|
||||
|
||||
public void setDisputeState(DisputeState disputeState) {
|
||||
Log.traceCall("disputeState=" + disputeState + "\n\ttrade=" + this);
|
||||
boolean changed = this.disputeState != disputeState;
|
||||
this.disputeState = disputeState;
|
||||
disputeStateProperty.set(disputeState);
|
||||
persist();
|
||||
if (changed)
|
||||
persist();
|
||||
}
|
||||
|
||||
public DisputeState getDisputeState() {
|
||||
|
@ -333,9 +337,11 @@ public abstract class Trade implements Tradable, Model {
|
|||
}
|
||||
|
||||
public void setTradePeriodState(TradePeriodState tradePeriodState) {
|
||||
boolean changed = this.tradePeriodState != tradePeriodState;
|
||||
this.tradePeriodState = tradePeriodState;
|
||||
tradePeriodStateProperty.set(tradePeriodState);
|
||||
persist();
|
||||
if (changed)
|
||||
persist();
|
||||
}
|
||||
|
||||
public TradePeriodState getTradePeriodState() {
|
||||
|
|
|
@ -75,8 +75,6 @@ import static io.bitsquare.util.Validator.nonEmptyStringOf;
|
|||
public class TradeManager {
|
||||
private static final Logger log = LoggerFactory.getLogger(TradeManager.class);
|
||||
|
||||
private static final long REPUBLISH_STATISTICS_INTERVAL_MIN = TimeUnit.HOURS.toMillis(1);
|
||||
|
||||
private final User user;
|
||||
private final KeyRing keyRing;
|
||||
private final WalletService walletService;
|
||||
|
@ -223,17 +221,9 @@ public class TradeManager {
|
|||
}
|
||||
|
||||
// We start later to have better connectivity to the network
|
||||
UserThread.runPeriodically(() -> publishTradeStatistics(tradesForStatistics),
|
||||
UserThread.runAfter(() -> publishTradeStatistics(tradesForStatistics),
|
||||
30, TimeUnit.SECONDS);
|
||||
|
||||
//TODO can be removed at next release
|
||||
// For the first 2 weeks of the release we re publish the trades to get faster good distribution
|
||||
// otherwise the trades would only be published again at restart and if a client dont do that the stats might be missing
|
||||
// for a longer time as initially there are not many peer upgraded and supporting flooding of the stats data.
|
||||
if (new Date().before(new Date(2016 - 1900, Calendar.AUGUST, 8)))
|
||||
UserThread.runPeriodically(() -> publishTradeStatistics(tradesForStatistics),
|
||||
REPUBLISH_STATISTICS_INTERVAL_MIN, TimeUnit.MILLISECONDS);
|
||||
|
||||
pendingTradesInitialized.set(true);
|
||||
}
|
||||
|
||||
|
@ -249,7 +239,8 @@ public class TradeManager {
|
|||
tradeStatisticsManager.add(tradeStatistics);
|
||||
|
||||
// Only trades from last 30 days
|
||||
if ((new Date().getTime() - trade.getDate().getTime()) < TimeUnit.DAYS.toMillis(30)) {
|
||||
//TODO we want to get old trades published so we dont do the 30 days check for the first few weeks of the new version
|
||||
if (new Date().before(new Date(2016 - 1900, Calendar.AUGUST, 30)) || (new Date().getTime() - trade.getDate().getTime()) < TimeUnit.DAYS.toMillis(30)) {
|
||||
long delay = 3000;
|
||||
final long minDelay = (i + 1) * delay;
|
||||
final long maxDelay = (i + 2) * delay;
|
||||
|
@ -289,7 +280,7 @@ public class TradeManager {
|
|||
// TODO respond
|
||||
//(RequestDepositTxInputsMessage)message.
|
||||
// messageService.sendEncryptedMessage(peerAddress,messageWithPubKey.getMessage().);
|
||||
log.info("We received a take offer request but don't have that offer anymore.");
|
||||
log.debug("We received a take offer request but don't have that offer anymore.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -391,7 +382,7 @@ public class TradeManager {
|
|||
@Override
|
||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction) {
|
||||
if (transaction != null) {
|
||||
log.info("onWithdraw onSuccess tx ID:" + transaction.getHashAsString());
|
||||
log.debug("onWithdraw onSuccess tx ID:" + transaction.getHashAsString());
|
||||
addTradeToClosedTrades(trade);
|
||||
trade.setState(Trade.State.WITHDRAW_COMPLETED);
|
||||
resultHandler.handleResult();
|
||||
|
|
|
@ -68,6 +68,7 @@ public final class OpenOffer implements Tradable {
|
|||
log.warn("Cannot be deserialized." + t.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return offer.getDate();
|
||||
}
|
||||
|
@ -92,8 +93,10 @@ public final class OpenOffer implements Tradable {
|
|||
|
||||
public void setState(State state) {
|
||||
log.trace("setState" + state);
|
||||
boolean changed = this.state != state;
|
||||
this.state = state;
|
||||
storage.queueUpForSave();
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
|
||||
// We keep it reserved for a limited time, if trade preparation fails we revert to available state
|
||||
if (this.state == State.RESERVED)
|
||||
|
@ -111,7 +114,7 @@ public final class OpenOffer implements Tradable {
|
|||
stopTimeout();
|
||||
|
||||
timeoutTimer = UserThread.runAfter(() -> {
|
||||
log.info("Timeout for resettin State.RESERVED reached");
|
||||
log.debug("Timeout for resettin State.RESERVED reached");
|
||||
if (state == State.RESERVED)
|
||||
setState(State.AVAILABLE);
|
||||
}, TIMEOUT_SEC);
|
||||
|
|
|
@ -152,7 +152,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
stopPeriodicRepublishOffersTimer();
|
||||
stopRetryRepublishOffersTimer();
|
||||
|
||||
log.info("remove all open offers at shutDown");
|
||||
log.debug("remove all open offers at shutDown");
|
||||
// we remove own offers from offerbook when we go offline
|
||||
// Normally we use a delay for broadcasting to the peers, but at shut down we want to get it fast out
|
||||
|
||||
|
@ -407,12 +407,12 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
|
||||
@Override
|
||||
public void onFault() {
|
||||
log.info("Sending OfferAvailabilityResponse failed.");
|
||||
log.debug("Sending OfferAvailabilityResponse failed.");
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
log.info("Exception at handleRequestIsOfferAvailableMessage " + t.getMessage());
|
||||
log.debug("Exception at handleRequestIsOfferAvailableMessage " + t.getMessage());
|
||||
}
|
||||
} else {
|
||||
log.debug("We have stopped already. We ignore that handleOfferAvailabilityRequest call.");
|
||||
|
@ -505,7 +505,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
// we delay to avoid reaching throttle limits
|
||||
// roughly 4 offers per second
|
||||
|
||||
long delay = 150;
|
||||
long delay = 300;
|
||||
final long minDelay = (i + 1) * delay;
|
||||
final long maxDelay = (i + 2) * delay;
|
||||
final OpenOffer openOffer = openOffersList.get(i);
|
||||
|
@ -532,7 +532,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||
}
|
||||
|
||||
private void restart() {
|
||||
log.info("Restart after connection loss");
|
||||
log.debug("Restart after connection loss");
|
||||
if (retryRepublishOffersTimer == null)
|
||||
retryRepublishOffersTimer = UserThread.runAfter(() -> {
|
||||
stopped = false;
|
||||
|
|
|
@ -135,7 +135,7 @@ public class OfferAvailabilityProtocol {
|
|||
private void startTimeout() {
|
||||
if (timeoutTimer == null) {
|
||||
timeoutTimer = UserThread.runAfter(() -> {
|
||||
log.warn("Timeout reached at " + this);
|
||||
log.debug("Timeout reached at " + this);
|
||||
model.offer.setState(Offer.State.OFFERER_OFFLINE);
|
||||
errorMessageHandler.handleErrorMessage("Timeout reached: Peer has not responded.");
|
||||
}, TIMEOUT_SEC);
|
||||
|
|
|
@ -44,7 +44,7 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
|
|||
model.tradeWalletService.broadcastTx(model.getTransaction(), new FutureCallback<Transaction>() {
|
||||
@Override
|
||||
public void onSuccess(Transaction transaction) {
|
||||
log.info("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
|
||||
log.debug("Broadcast of offer fee payment succeeded: transaction = " + transaction.toString());
|
||||
|
||||
if (model.getTransaction().getHashAsString().equals(transaction.getHashAsString())) {
|
||||
model.offer.setState(Offer.State.OFFER_FEE_PAID);
|
||||
|
@ -57,7 +57,7 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
|
|||
// Normally we use a delay for broadcasting to the peers, but at shut down we want to get it fast out
|
||||
model.offerBookService.removeOffer(model.offer,
|
||||
() -> {
|
||||
log.info("We store now the changed txID to the offer and add that again.");
|
||||
log.debug("We store now the changed txID to the offer and add that again.");
|
||||
// We store now the changed txID to the offer and add that again.
|
||||
model.offer.setOfferFeePaymentTxID(transaction.getHashAsString());
|
||||
model.setTransaction(transaction);
|
||||
|
@ -106,7 +106,7 @@ public class BroadcastCreateOfferFeeTx extends Task<PlaceOfferModel> {
|
|||
if (!removeOfferFailed && !addOfferFailed) {
|
||||
// If broadcast fails we need to remove offer from offerbook
|
||||
model.offerBookService.removeOffer(model.offer,
|
||||
() -> log.info("Offer removed from offerbook because broadcast failed."),
|
||||
() -> log.debug("Offer removed from offerbook because broadcast failed."),
|
||||
errorMessage -> log.error("removeOffer failed. " + errorMessage));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ public abstract class TradeTask extends Task<Trade> {
|
|||
if (processModel.getTradeMessage() instanceof MailboxMessage) {
|
||||
DecryptedMsgWithPubKey mailboxMessage = trade.getMailboxMessage();
|
||||
if (mailboxMessage != null && mailboxMessage.message.equals(processModel.getTradeMessage())) {
|
||||
log.info("Remove mailboxMessage from P2P network. mailboxMessage = " + mailboxMessage);
|
||||
log.debug("Remove mailboxMessage from P2P network. mailboxMessage = " + mailboxMessage);
|
||||
processModel.getP2PService().removeEntryFromMailbox(mailboxMessage);
|
||||
trade.setMailboxMessage(null);
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class OffererCreatesAndSignsDepositTxAsBuyer extends TradeTask {
|
|||
Coin buyerInputAmount = FeePolicy.getSecurityDeposit().add(FeePolicy.getFixedTxFeeForTrades());
|
||||
Coin msOutputAmount = buyerInputAmount.add(FeePolicy.getSecurityDeposit()).add(trade.getTradeAmount());
|
||||
|
||||
log.info("\n\n------------------------------------------------------------\n"
|
||||
log.debug("\n\n------------------------------------------------------------\n"
|
||||
+ "Contract as json\n"
|
||||
+ trade.getContractAsJson()
|
||||
+ "\n------------------------------------------------------------\n");
|
||||
|
|
|
@ -48,14 +48,14 @@ public class SendFiatTransferStartedMessage extends TradeTask {
|
|||
new SendMailboxMessageListener() {
|
||||
@Override
|
||||
public void onArrived() {
|
||||
log.info("Message arrived at peer.");
|
||||
log.debug("Message arrived at peer.");
|
||||
trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStoredInMailbox() {
|
||||
log.info("Message stored in mailbox.");
|
||||
log.debug("Message stored in mailbox.");
|
||||
trade.setState(Trade.State.BUYER_SENT_FIAT_PAYMENT_INITIATED_MSG);
|
||||
complete();
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ public class SignAndPublishDepositTxAsBuyer extends TradeTask {
|
|||
try {
|
||||
runInterceptHook();
|
||||
|
||||
log.info("\n\n------------------------------------------------------------\n"
|
||||
log.debug("\n\n------------------------------------------------------------\n"
|
||||
+ "Contract as json\n"
|
||||
+ trade.getContractAsJson()
|
||||
+ "\n------------------------------------------------------------\n");
|
||||
|
|
|
@ -46,7 +46,7 @@ public class OffererCreatesAndSignsDepositTxAsSeller extends TradeTask {
|
|||
Coin sellerInputAmount = FeePolicy.getSecurityDeposit().add(FeePolicy.getFixedTxFeeForTrades()).add(trade.getTradeAmount());
|
||||
Coin msOutputAmount = sellerInputAmount.add(FeePolicy.getSecurityDeposit());
|
||||
|
||||
log.info("\n\n------------------------------------------------------------\n"
|
||||
log.debug("\n\n------------------------------------------------------------\n"
|
||||
+ "Contract as json\n"
|
||||
+ trade.getContractAsJson()
|
||||
+ "\n------------------------------------------------------------\n");
|
||||
|
|
|
@ -46,7 +46,7 @@ public class SignAndPublishDepositTxAsSeller extends TradeTask {
|
|||
protected void run() {
|
||||
try {
|
||||
runInterceptHook();
|
||||
log.info("\n\n------------------------------------------------------------\n"
|
||||
log.debug("\n\n------------------------------------------------------------\n"
|
||||
+ "Contract as json\n"
|
||||
+ trade.getContractAsJson()
|
||||
+ "\n------------------------------------------------------------\n");
|
||||
|
|
|
@ -64,7 +64,7 @@ public class PublishTradeStatistics extends TradeTask {
|
|||
}
|
||||
}
|
||||
if (!matches) {
|
||||
log.warn("We publish tradeStatistics because the offerer uses an old version.");
|
||||
log.debug("We publish tradeStatistics because the offerer uses an old version so we publish to have at least 1 data item published.");
|
||||
processModel.getP2PService().addData(tradeStatistics, true);
|
||||
} else {
|
||||
log.trace("We do not publish tradeStatistics because the offerer support the capabilities.");
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.google.inject.Inject;
|
|||
import com.google.inject.name.Named;
|
||||
import io.bitsquare.app.CoreOptionKeys;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.locale.CurrencyTuple;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
import io.bitsquare.p2p.storage.HashMapChangedListener;
|
||||
import io.bitsquare.p2p.storage.payload.StoragePayload;
|
||||
|
@ -14,6 +16,7 @@ import javafx.collections.ObservableSet;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -21,22 +24,44 @@ import java.util.stream.Collectors;
|
|||
public class TradeStatisticsManager {
|
||||
private static final Logger log = LoggerFactory.getLogger(TradeStatisticsManager.class);
|
||||
|
||||
private final Storage<HashSet<TradeStatistics>> storage;
|
||||
private Storage<String> jsonStorage;
|
||||
private final Storage<HashSet<TradeStatistics>> statisticsStorage;
|
||||
private Storage<String> fiatCurrencyListJsonStorage;
|
||||
private Storage<String> cryptoCurrencyListJsonStorage;
|
||||
private Storage<String> statisticsJsonStorage;
|
||||
private boolean dumpStatistics;
|
||||
private ObservableSet<TradeStatistics> observableTradeStatisticsSet = FXCollections.observableSet();
|
||||
private HashSet<TradeStatistics> tradeStatisticsSet = new HashSet<>();
|
||||
|
||||
@Inject
|
||||
public TradeStatisticsManager(Storage<HashSet<TradeStatistics>> storage, Storage<String> jsonStorage, P2PService p2PService, @Named(CoreOptionKeys.DUMP_STATISTICS) boolean dumpStatistics) {
|
||||
this.storage = storage;
|
||||
this.jsonStorage = jsonStorage;
|
||||
public TradeStatisticsManager(Storage<HashSet<TradeStatistics>> statisticsStorage,
|
||||
Storage<String> fiatCurrencyListJsonStorage,
|
||||
Storage<String> cryptoCurrencyListJsonStorage,
|
||||
Storage<String> statisticsJsonStorage,
|
||||
P2PService p2PService,
|
||||
@Named(CoreOptionKeys.DUMP_STATISTICS) boolean dumpStatistics) {
|
||||
this.statisticsStorage = statisticsStorage;
|
||||
this.fiatCurrencyListJsonStorage = fiatCurrencyListJsonStorage;
|
||||
this.cryptoCurrencyListJsonStorage = cryptoCurrencyListJsonStorage;
|
||||
this.statisticsJsonStorage = statisticsJsonStorage;
|
||||
this.dumpStatistics = dumpStatistics;
|
||||
|
||||
if (dumpStatistics)
|
||||
this.jsonStorage.initAndGetPersistedWithFileName("trade_statistics.json");
|
||||
if (dumpStatistics) {
|
||||
this.statisticsJsonStorage.initAndGetPersistedWithFileName("trade_statistics.json");
|
||||
|
||||
HashSet<TradeStatistics> persisted = storage.initAndGetPersistedWithFileName("TradeStatistics");
|
||||
this.fiatCurrencyListJsonStorage.initAndGetPersistedWithFileName("fiat_currency_list.json");
|
||||
ArrayList<CurrencyTuple> fiatCurrencyList = new ArrayList<>(CurrencyUtil.getAllSortedFiatCurrencies().stream()
|
||||
.map(e -> new CurrencyTuple(e.getCode(), e.getName()))
|
||||
.collect(Collectors.toList()));
|
||||
fiatCurrencyListJsonStorage.queueUpForSave(Utilities.objectToJson(fiatCurrencyList), 2000);
|
||||
|
||||
this.cryptoCurrencyListJsonStorage.initAndGetPersistedWithFileName("crypto_currency_list.json");
|
||||
ArrayList<CurrencyTuple> cryptoCurrencyList = new ArrayList<>(CurrencyUtil.getAllSortedCryptoCurrencies().stream()
|
||||
.map(e -> new CurrencyTuple(e.getCode(), e.getName()))
|
||||
.collect(Collectors.toList()));
|
||||
cryptoCurrencyListJsonStorage.queueUpForSave(Utilities.objectToJson(cryptoCurrencyList), 2000);
|
||||
}
|
||||
|
||||
HashSet<TradeStatistics> persisted = statisticsStorage.initAndGetPersistedWithFileName("TradeStatistics");
|
||||
if (persisted != null)
|
||||
persisted.stream().forEach(this::add);
|
||||
|
||||
|
@ -44,7 +69,7 @@ public class TradeStatisticsManager {
|
|||
@Override
|
||||
public void onAdded(ProtectedStorageEntry data) {
|
||||
final StoragePayload storagePayload = data.getStoragePayload();
|
||||
if (storagePayload instanceof TradeStatistics)
|
||||
if (storagePayload instanceof TradeStatistics)
|
||||
add((TradeStatistics) storagePayload);
|
||||
}
|
||||
|
||||
|
@ -61,7 +86,7 @@ public class TradeStatisticsManager {
|
|||
if (!itemAlreadyAdded) {
|
||||
tradeStatisticsSet.add(tradeStatistics);
|
||||
observableTradeStatisticsSet.add(tradeStatistics);
|
||||
storage.queueUpForSave(tradeStatisticsSet, 2000);
|
||||
statisticsStorage.queueUpForSave(new HashSet<>(tradeStatisticsSet), 2000);
|
||||
|
||||
dump();
|
||||
} else {
|
||||
|
@ -86,7 +111,7 @@ public class TradeStatisticsManager {
|
|||
list.sort((o1, o2) -> (o1.tradeDate < o2.tradeDate ? 1 : (o1.tradeDate == o2.tradeDate ? 0 : -1)));
|
||||
TradeStatistics[] array = new TradeStatistics[tradeStatisticsSet.size()];
|
||||
list.toArray(array);
|
||||
jsonStorage.queueUpForSave(Utilities.objectToJson(array), 5_000);
|
||||
statisticsJsonStorage.queueUpForSave(Utilities.objectToJson(array), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,8 +121,10 @@ public final class Preferences implements Persistable {
|
|||
private long nonTradeTxFeePerKB = FeePolicy.getNonTradeFeePerKb().value;
|
||||
private double maxPriceDistanceInPercent;
|
||||
private boolean useInvertedMarketPrice;
|
||||
private String marketScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||
private String tradeStatisticsScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||
|
||||
private String offerBookChartScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||
private String tradeChartsScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||
|
||||
private String buyScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||
private String sellScreenCurrencyCode = CurrencyUtil.getDefaultTradeCurrency().getCode();
|
||||
private int tradeStatisticsTickUnitIndex = 0;
|
||||
|
@ -215,10 +217,10 @@ public final class Preferences implements Persistable {
|
|||
if (persisted.getPeerTagMap() != null)
|
||||
peerTagMap = persisted.getPeerTagMap();
|
||||
|
||||
marketScreenCurrencyCode = persisted.getMarketScreenCurrencyCode();
|
||||
offerBookChartScreenCurrencyCode = persisted.getOfferBookChartScreenCurrencyCode();
|
||||
buyScreenCurrencyCode = persisted.getBuyScreenCurrencyCode();
|
||||
sellScreenCurrencyCode = persisted.getSellScreenCurrencyCode();
|
||||
tradeStatisticsScreenCurrencyCode = persisted.getTradeStatisticsScreenCurrencyCode();
|
||||
tradeChartsScreenCurrencyCode = persisted.getTradeChartsScreenCurrencyCode();
|
||||
tradeStatisticsTickUnitIndex = persisted.getTradeStatisticsTickUnitIndex();
|
||||
|
||||
if (persisted.getIgnoreTradersList() != null)
|
||||
|
@ -449,8 +451,8 @@ public final class Preferences implements Persistable {
|
|||
}
|
||||
}
|
||||
|
||||
public void setMarketScreenCurrencyCode(String marketScreenCurrencyCode) {
|
||||
this.marketScreenCurrencyCode = marketScreenCurrencyCode;
|
||||
public void setOfferBookChartScreenCurrencyCode(String offerBookChartScreenCurrencyCode) {
|
||||
this.offerBookChartScreenCurrencyCode = offerBookChartScreenCurrencyCode;
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
|
@ -474,8 +476,8 @@ public final class Preferences implements Persistable {
|
|||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void setTradeStatisticsScreenCurrencyCode(String tradeStatisticsScreenCurrencyCode) {
|
||||
this.tradeStatisticsScreenCurrencyCode = tradeStatisticsScreenCurrencyCode;
|
||||
public void setTradeChartsScreenCurrencyCode(String tradeChartsScreenCurrencyCode) {
|
||||
this.tradeChartsScreenCurrencyCode = tradeChartsScreenCurrencyCode;
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
|
@ -486,6 +488,7 @@ public final class Preferences implements Persistable {
|
|||
|
||||
public void setUseTorForHttpRequests(boolean useTorForHttpRequests) {
|
||||
useTorForHttpRequestsProperty.set(useTorForHttpRequests);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -620,8 +623,8 @@ public final class Preferences implements Persistable {
|
|||
return bridgeAddresses;
|
||||
}
|
||||
|
||||
public String getMarketScreenCurrencyCode() {
|
||||
return marketScreenCurrencyCode;
|
||||
public String getOfferBookChartScreenCurrencyCode() {
|
||||
return offerBookChartScreenCurrencyCode;
|
||||
}
|
||||
|
||||
public String getBuyScreenCurrencyCode() {
|
||||
|
@ -640,8 +643,8 @@ public final class Preferences implements Persistable {
|
|||
return defaultPath;
|
||||
}
|
||||
|
||||
public String getTradeStatisticsScreenCurrencyCode() {
|
||||
return tradeStatisticsScreenCurrencyCode;
|
||||
public String getTradeChartsScreenCurrencyCode() {
|
||||
return tradeChartsScreenCurrencyCode;
|
||||
}
|
||||
|
||||
public int getTradeStatisticsTickUnitIndex() {
|
||||
|
@ -679,11 +682,11 @@ public final class Preferences implements Persistable {
|
|||
|
||||
private void setBlockChainExplorerTestNet(BlockChainExplorer blockChainExplorerTestNet) {
|
||||
this.blockChainExplorerTestNet = blockChainExplorerTestNet;
|
||||
storage.queueUpForSave(2000);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
private void setBlockChainExplorerMainNet(BlockChainExplorer blockChainExplorerMainNet) {
|
||||
this.blockChainExplorerMainNet = blockChainExplorerMainNet;
|
||||
storage.queueUpForSave(2000);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,8 +181,9 @@ public final class User implements Persistable {
|
|||
|
||||
public void addAcceptedArbitrator(Arbitrator arbitrator) {
|
||||
if (!acceptedArbitrators.contains(arbitrator) && !isMyOwnRegisteredArbitrator(arbitrator)) {
|
||||
acceptedArbitrators.add(arbitrator);
|
||||
storage.queueUpForSave();
|
||||
boolean changed = acceptedArbitrators.add(arbitrator);
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,8 +192,9 @@ public final class User implements Persistable {
|
|||
}
|
||||
|
||||
public void removeAcceptedArbitrator(Arbitrator arbitrator) {
|
||||
acceptedArbitrators.remove(arbitrator);
|
||||
storage.queueUpForSave();
|
||||
boolean changed = acceptedArbitrators.remove(arbitrator);
|
||||
if (changed)
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void clearAcceptedArbitrators() {
|
||||
|
@ -200,7 +202,7 @@ public final class User implements Persistable {
|
|||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public void setRegisteredArbitrator(@org.jetbrains.annotations.Nullable Arbitrator arbitrator) {
|
||||
public void setRegisteredArbitrator(@Nullable Arbitrator arbitrator) {
|
||||
this.registeredArbitrator = arbitrator;
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
@ -330,7 +332,7 @@ public final class User implements Persistable {
|
|||
|
||||
public void setDevelopersAlert(Alert developersAlert) {
|
||||
this.developersAlert = developersAlert;
|
||||
storage.queueUpForSave(2000);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public Alert getDevelopersAlert() {
|
||||
|
@ -339,7 +341,7 @@ public final class User implements Persistable {
|
|||
|
||||
public void setDisplayedAlert(Alert displayedAlert) {
|
||||
this.displayedAlert = displayedAlert;
|
||||
storage.queueUpForSave(2000);
|
||||
storage.queueUpForSave();
|
||||
}
|
||||
|
||||
public Alert getDisplayedAlert() {
|
||||
|
|
|
@ -71,11 +71,11 @@ You need to get the Bitsquare dependencies first as we need to copy the BountyCa
|
|||
|
||||
### 4. Copy the jdkfix jar file
|
||||
|
||||
Copy the jdkfix-0.4.9.1.jar from the Bitsquare jdkfix/target directory to $JAVA_HOME/jre/lib/ext/.
|
||||
jdkfix-0.4.9.1.jar includes a bugfix of the SortedList class which will be released with the next JDK version.
|
||||
Copy the jdkfix-0.4.9.2.jar from the Bitsquare jdkfix/target directory to $JAVA_HOME/jre/lib/ext/.
|
||||
jdkfix-0.4.9.2.jar includes a bugfix of the SortedList class which will be released with the next JDK version.
|
||||
We need to load that class before the default java class. This step will be removed once the bugfix is in the official JDK.
|
||||
|
||||
$ sudo cp bitsquare/jdkfix/target/jdkfix-0.4.9.1.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.1.jar
|
||||
$ sudo cp bitsquare/jdkfix/target/jdkfix-0.4.9.2.jar $JAVA_HOME/jre/lib/ext/jdkfix-0.4.9.2.jar
|
||||
|
||||
### 5. Copy the BountyCastle provider jar file
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -265,7 +265,7 @@ public class BitsquareApp extends Application {
|
|||
private void showErrorPopup(Throwable throwable, boolean doShutDown) {
|
||||
if (!shutDownRequested) {
|
||||
if (scene == null) {
|
||||
log.warn("Scene not available yet, we create a new scene. The bug might be caused by a guice circular dependency.");
|
||||
log.warn("Scene not available yet, we create a new scene. The bug might be caused by an exception in a constructor or by a circular dependency in guice.");
|
||||
scene = new Scene(new StackPane(), 1000, 650);
|
||||
scene.getStylesheets().setAll(
|
||||
"/io/bitsquare/gui/bitsquare.css",
|
||||
|
@ -357,7 +357,7 @@ public class BitsquareApp extends Application {
|
|||
.show();
|
||||
UserThread.runAfter(() -> {
|
||||
gracefulShutDown(() -> {
|
||||
log.info("App shutdown complete");
|
||||
log.debug("App shutdown complete");
|
||||
System.exit(0);
|
||||
});
|
||||
}, 200, TimeUnit.MILLISECONDS);
|
||||
|
@ -376,7 +376,7 @@ public class BitsquareApp extends Application {
|
|||
injector.getInstance(P2PService.class).shutDown(() -> {
|
||||
injector.getInstance(WalletService.class).shutDownDone.addListener((ov, o, n) -> {
|
||||
bitsquareAppModule.close(injector);
|
||||
log.info("Graceful shutdown completed");
|
||||
log.debug("Graceful shutdown completed");
|
||||
resultHandler.handleResult();
|
||||
});
|
||||
injector.getInstance(WalletService.class).shutDown();
|
||||
|
@ -388,7 +388,7 @@ public class BitsquareApp extends Application {
|
|||
UserThread.runAfter(resultHandler::handleResult, 1);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.info("App shutdown failed with exception");
|
||||
log.debug("App shutdown failed with exception");
|
||||
t.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
|
|
@ -80,10 +80,6 @@
|
|||
-fx-background-insets: 0, 1, 2;
|
||||
}
|
||||
|
||||
.volume-bar.bg {
|
||||
-demo-bar-fill: #70bfc6;
|
||||
}
|
||||
|
||||
.volume-bar {
|
||||
-fx-effect: dropshadow(two-pass-box, rgba(0, 0, 0, 0.4), 10, 0.0, 2, 4);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import io.bitsquare.common.persistance.Persistable;
|
|||
import io.bitsquare.gui.common.view.View;
|
||||
import io.bitsquare.gui.common.view.ViewPath;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.markets.MarketView;
|
||||
import io.bitsquare.gui.main.market.MarketView;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -101,7 +101,7 @@ public final class Navigation implements Persistable {
|
|||
|
||||
currentPath = newPath;
|
||||
previousPath = currentPath;
|
||||
storage.queueUpForSave(2000);
|
||||
storage.queueUpForSave(1000);
|
||||
listeners.stream().forEach((e) -> e.onNavigationRequested(currentPath));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package io.bitsquare.gui;
|
|||
import io.bitsquare.BitsquareException;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.ImageUtil;
|
||||
import javafx.application.Platform;
|
||||
import javafx.stage.Stage;
|
||||
|
@ -123,7 +124,7 @@ public class SystemTray {
|
|||
|
||||
aboutItem.addActionListener(e -> {
|
||||
try {
|
||||
Utilities.openWebPage("https://bitsquare.io");
|
||||
GUIUtil.openWebPage("https://bitsquare.io");
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ Theme colors:
|
|||
|
||||
logo colors:
|
||||
|
||||
new blue: 0f87c3
|
||||
new grey: 666666
|
||||
Bitsquare blue: 0f86c3
|
||||
Bitsquare grey: 666666
|
||||
|
||||
00abff
|
||||
orange web page quotes : ff7f00
|
||||
|
|
|
@ -24,6 +24,7 @@ import io.bitsquare.btc.listeners.TxConfidenceListener;
|
|||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.components.indicator.TxConfidenceIndicator;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
|
@ -135,7 +136,7 @@ public class TxIdTextField extends AnchorPane {
|
|||
private void openBlockExplorer(String txID) {
|
||||
try {
|
||||
if (preferences != null)
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().txUrl + txID);
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().txUrl + txID);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
|
|
@ -24,20 +24,20 @@ import io.bitsquare.btc.pricefeed.PriceFeedService;
|
|||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.view.*;
|
||||
import io.bitsquare.gui.components.BusyAnimation;
|
||||
import io.bitsquare.gui.main.account.AccountView;
|
||||
import io.bitsquare.gui.main.disputes.DisputesView;
|
||||
import io.bitsquare.gui.main.funds.FundsView;
|
||||
import io.bitsquare.gui.main.markets.MarketView;
|
||||
import io.bitsquare.gui.main.market.MarketView;
|
||||
import io.bitsquare.gui.main.offer.BuyOfferView;
|
||||
import io.bitsquare.gui.main.offer.SellOfferView;
|
||||
import io.bitsquare.gui.main.overlays.Overlay;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
||||
import io.bitsquare.gui.main.settings.SettingsView;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.Transitions;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.geometry.Insets;
|
||||
|
@ -227,19 +227,24 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
|||
navigation.navigateToPreviousVisitedView();
|
||||
|
||||
if (!persistedFilesCorrupted.isEmpty()) {
|
||||
// show warning that some files has been corrupted
|
||||
new Popup().warning("We detected incompatible data base files!\n\n" +
|
||||
"Those database file(s) are not compatible with our current code base:" +
|
||||
"\n" + persistedFilesCorrupted.toString() +
|
||||
"\n\nWe made a backup of the corrupted file(s) and applied the default values to a new " +
|
||||
"database version." +
|
||||
"\n\nThe backup is located at:\n[you local app data directory]/db/backup_of_corrupted_data.\n\n" +
|
||||
"Please check if you have the latest version of Bitsquare installed.\n" +
|
||||
"You can download it at:\nhttps://github.com/bitsquare/bitsquare/releases\n\n" +
|
||||
"Please restart the application.")
|
||||
.closeButtonText("Shut down")
|
||||
.onClose(BitsquareApp.shutDownHandler::run)
|
||||
.show();
|
||||
if (persistedFilesCorrupted.size() > 1 || !persistedFilesCorrupted.get(0).equals("Navigation")) {
|
||||
// show warning that some files has been corrupted
|
||||
new Popup().warning("We detected incompatible data base files!\n\n" +
|
||||
"Those database file(s) are not compatible with our current code base:" +
|
||||
"\n" + persistedFilesCorrupted.toString() +
|
||||
"\n\nWe made a backup of the corrupted file(s) and applied the default values to a new " +
|
||||
"database version." +
|
||||
"\n\nThe backup is located at:\n[you local app data directory]/db/backup_of_corrupted_data.\n\n" +
|
||||
"Please check if you have the latest version of Bitsquare installed.\n" +
|
||||
"You can download it at:\nhttps://github.com/bitsquare/bitsquare/releases\n\n" +
|
||||
"Please restart the application.")
|
||||
.closeButtonText("Shut down")
|
||||
.onClose(BitsquareApp.shutDownHandler::run)
|
||||
.show();
|
||||
} else {
|
||||
log.debug("We detected incompatible data base file for Navigation. That is a minor issue happening with refactoring of UI classes " +
|
||||
"and we don't display a warning popup to the user.");
|
||||
}
|
||||
}
|
||||
|
||||
transitions.fadeOutAndRemove(splashScreen, 1500, actionEvent -> disposeSplashScreen());
|
||||
|
@ -320,7 +325,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
|||
btcAverageIconButton.setFocusTraversable(false);
|
||||
btcAverageIconButton.setStyle("-fx-background-color: transparent;");
|
||||
HBox.setMargin(btcAverageIconButton, new Insets(0, 27, 0, 0));
|
||||
btcAverageIconButton.setOnAction(e -> Utilities.openWebPage("https://bitcoinaverage.com"));
|
||||
btcAverageIconButton.setOnAction(e -> GUIUtil.openWebPage("https://bitcoinaverage.com"));
|
||||
btcAverageIconButton.visibleProperty().bind(model.isFiatCurrencyPriceFeedSelected);
|
||||
btcAverageIconButton.managedProperty().bind(model.isFiatCurrencyPriceFeedSelected);
|
||||
btcAverageIconButton.setTooltip(new Tooltip("Market price is provided by https://bitcoinaverage.com"));
|
||||
|
@ -332,7 +337,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
|||
poloniexIconButton.setFocusTraversable(false);
|
||||
poloniexIconButton.setStyle("-fx-background-color: transparent;");
|
||||
HBox.setMargin(poloniexIconButton, new Insets(1, 27, 0, 0));
|
||||
poloniexIconButton.setOnAction(e -> Utilities.openWebPage("https://poloniex.com"));
|
||||
poloniexIconButton.setOnAction(e -> GUIUtil.openWebPage("https://poloniex.com"));
|
||||
poloniexIconButton.visibleProperty().bind(model.isCryptoCurrencyPriceFeedSelected);
|
||||
poloniexIconButton.managedProperty().bind(model.isCryptoCurrencyPriceFeedSelected);
|
||||
poloniexIconButton.setTooltip(new Tooltip("Market price is provided by https://poloniex.com"));
|
||||
|
|
|
@ -39,7 +39,6 @@ import io.bitsquare.common.Clock;
|
|||
import io.bitsquare.common.Timer;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.crypto.*;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.filter.FilterManager;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.ViewModel;
|
||||
|
@ -53,6 +52,7 @@ import io.bitsquare.gui.main.overlays.windows.DisplayAlertMessageWindow;
|
|||
import io.bitsquare.gui.main.overlays.windows.TacWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
|
@ -322,8 +322,8 @@ public class MainViewModel implements ViewModel {
|
|||
// Other disconnects might be caused by peers running an older version
|
||||
if (connection.getPeerType() == Connection.PeerType.SEED_NODE &&
|
||||
closeConnectionReason == CloseConnectionReason.RULE_VIOLATION) {
|
||||
log.warn("onDisconnect closeConnectionReason=" + closeConnectionReason);
|
||||
log.warn("onDisconnect connection=" + connection);
|
||||
log.warn("RULE_VIOLATION onDisconnect closeConnectionReason=" + closeConnectionReason);
|
||||
log.warn("RULE_VIOLATION onDisconnect connection=" + connection);
|
||||
//TODO
|
||||
/* new Popup()
|
||||
.warning("You got disconnected from a seed node.\n\n" +
|
||||
|
@ -590,7 +590,7 @@ public class MainViewModel implements ViewModel {
|
|||
.actionButtonText("Shut down")
|
||||
.onAction(BitsquareApp.shutDownHandler::run)
|
||||
.closeButtonText("Report bug at Github issues")
|
||||
.onClose(() -> Utilities.openWebPage("https://github.com/bitsquare/bitsquare/issues"))
|
||||
.onClose(() -> GUIUtil.openWebPage("https://github.com/bitsquare/bitsquare/issues"))
|
||||
.show());
|
||||
}
|
||||
}
|
||||
|
@ -602,7 +602,7 @@ public class MainViewModel implements ViewModel {
|
|||
.actionButtonText("Shut down")
|
||||
.onAction(BitsquareApp.shutDownHandler::run)
|
||||
.closeButtonText("Report bug at Github issues")
|
||||
.onClose(() -> Utilities.openWebPage("https://github.com/bitsquare/bitsquare/issues"))
|
||||
.onClose(() -> GUIUtil.openWebPage("https://github.com/bitsquare/bitsquare/issues"))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
@ -846,6 +846,8 @@ public class MainViewModel implements ViewModel {
|
|||
else
|
||||
findPriceFeedComboBoxItem(preferences.getPreferredTradeCurrency().getCode())
|
||||
.ifPresent(item2 -> selectedPriceFeedComboBoxItemProperty.set(item2));
|
||||
|
||||
priceFeedService.setCurrencyCode(item.currencyCode);
|
||||
} else if (item != null) {
|
||||
selectedPriceFeedComboBoxItemProperty.set(item);
|
||||
priceFeedService.setCurrencyCode(item.currencyCode);
|
||||
|
|
|
@ -20,17 +20,13 @@ package io.bitsquare.gui.main.account.content.altcoinaccounts;
|
|||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.components.paymentmethods.CryptoCurrencyForm;
|
||||
import io.bitsquare.gui.components.paymentmethods.PaymentMethodForm;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.FormBuilder;
|
||||
import io.bitsquare.gui.util.ImageUtil;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.gui.util.*;
|
||||
import io.bitsquare.gui.util.validation.*;
|
||||
import io.bitsquare.locale.CryptoCurrency;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
|
@ -173,7 +169,7 @@ public class AltCoinAccountsView extends ActivatableViewAndModel<GridPane, AltCo
|
|||
new Popup().information("The EHT/ETC fork situation carries considerable risks.\n" +
|
||||
"Be sure you fully understand the situation and check out the information on the \"Ethereum Classic\" and \"Ethereum\" project web pages.")
|
||||
.closeButtonText("I understand")
|
||||
.onAction(() -> Utilities.openWebPage("https://ethereumclassic.github.io/"))
|
||||
.onAction(() -> GUIUtil.openWebPage("https://ethereumclassic.github.io/"))
|
||||
.actionButtonText("Open Ethereum Classic web page")
|
||||
.show();
|
||||
}
|
||||
|
|
|
@ -263,7 +263,6 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
|
|||
}
|
||||
|
||||
private void doRestore() {
|
||||
log.info("Attempting wallet restore using seed '{}' from date {}", restoreSeedWordsTextArea.getText(), restoreDatePicker.getValue());
|
||||
long date = restoreDatePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC);
|
||||
DeterministicSeed seed = new DeterministicSeed(Splitter.on(" ").splitToList(restoreSeedWordsTextArea.getText()), null, "", date);
|
||||
walletService.restoreSeedWords(seed,
|
||||
|
|
|
@ -25,7 +25,6 @@ import io.bitsquare.btc.WalletService;
|
|||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.common.view.ActivatableView;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.components.AddressTextField;
|
||||
|
@ -278,7 +277,7 @@ public class DepositView extends ActivatableView<VBox, Void> {
|
|||
private void openBlockExplorer(DepositListItem item) {
|
||||
if (item.getAddressString() != null) {
|
||||
try {
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
|
|
@ -21,7 +21,6 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
|
|||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.common.view.ActivatableView;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||
|
@ -29,6 +28,7 @@ import io.bitsquare.gui.main.overlays.popups.Popup;
|
|||
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.trade.Tradable;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
|
@ -157,7 +157,7 @@ public class LockedView extends ActivatableView<VBox, Void> {
|
|||
|
||||
private void openBlockExplorer(LockedListItem item) {
|
||||
try {
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
|
|
@ -21,7 +21,6 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
|
|||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.common.view.ActivatableView;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||
|
@ -29,6 +28,7 @@ import io.bitsquare.gui.main.overlays.popups.Popup;
|
|||
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
|
||||
import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.trade.Tradable;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
|
@ -157,7 +157,7 @@ public class ReservedView extends ActivatableView<VBox, Void> {
|
|||
|
||||
private void openBlockExplorer(ReservedListItem item) {
|
||||
try {
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
|
|
@ -294,7 +294,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
|||
private void openTxInBlockExplorer(TransactionsListItem item) {
|
||||
if (item.getTxId() != null) {
|
||||
try {
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().txUrl + item.getTxId());
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().txUrl + item.getTxId());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
@ -306,7 +306,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
|
|||
private void openAddressInBlockExplorer(TransactionsListItem item) {
|
||||
if (item.getAddressString() != null) {
|
||||
try {
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
|
|
@ -25,13 +25,13 @@ import io.bitsquare.btc.AddressEntryException;
|
|||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.common.view.ActivatableView;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.validation.BtcAddressValidator;
|
||||
import io.bitsquare.trade.Tradable;
|
||||
import io.bitsquare.trade.Trade;
|
||||
|
@ -185,7 +185,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
|
|||
@Override
|
||||
public void onSuccess(@javax.annotation.Nullable Transaction transaction) {
|
||||
if (transaction != null) {
|
||||
log.info("onWithdraw onSuccess tx ID:" + transaction.getHashAsString());
|
||||
log.debug("onWithdraw onSuccess tx ID:" + transaction.getHashAsString());
|
||||
} else {
|
||||
log.error("onWithdraw transaction is null");
|
||||
}
|
||||
|
@ -287,7 +287,7 @@ public class WithdrawalView extends ActivatableView<VBox, Void> {
|
|||
private void openBlockExplorer(WithdrawalListItem item) {
|
||||
if (item.getAddressString() != null) {
|
||||
try {
|
||||
Utilities.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
GUIUtil.openWebPage(preferences.getBlockChainExplorer().addressUrl + item.getAddressString());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
new Popup().warning("Opening browser failed. Please check your internet " +
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
|
||||
package io.bitsquare.gui.main.help;
|
||||
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class Help {
|
|||
public static void openWindow(HelpId id) {
|
||||
try {
|
||||
// TODO create user guide
|
||||
Utilities.openWebPage("http://bitsquare.io/faq");
|
||||
GUIUtil.openWebPage("http://bitsquare.io/faq");
|
||||
// Utilities.openWebPage("https://github.com/bitsquare/bitsquare/wiki/User-Guide");
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage());
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<?import javafx.scene.control.Tab?>
|
||||
<?import javafx.scene.control.TabPane?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.markets.MarketView"
|
||||
<TabPane fx:id="root" fx:controller="io.bitsquare.gui.main.market.MarketView"
|
||||
AnchorPane.bottomAnchor="0" AnchorPane.leftAnchor="0"
|
||||
AnchorPane.rightAnchor="0" AnchorPane.topAnchor="0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
|
@ -15,15 +15,15 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets;
|
||||
package io.bitsquare.gui.main.market;
|
||||
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.Activatable;
|
||||
import io.bitsquare.gui.common.view.*;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.markets.charts.MarketsChartsView;
|
||||
import io.bitsquare.gui.main.markets.statistics.MarketsStatisticsView;
|
||||
import io.bitsquare.gui.main.markets.trades.TradesChartsView;
|
||||
import io.bitsquare.gui.main.market.offerbook.OfferBookChartView;
|
||||
import io.bitsquare.gui.main.market.spread.SpreadView;
|
||||
import io.bitsquare.gui.main.market.trades.TradesChartsView;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Tab;
|
||||
|
@ -55,11 +55,11 @@ public class MarketView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
|
||||
tabChangeListener = (ov, oldValue, newValue) -> {
|
||||
if (newValue == chartsTab)
|
||||
navigation.navigateTo(MainView.class, MarketView.class, MarketsChartsView.class);
|
||||
navigation.navigateTo(MainView.class, MarketView.class, OfferBookChartView.class);
|
||||
else if (newValue == tradesTab)
|
||||
navigation.navigateTo(MainView.class, MarketView.class, TradesChartsView.class);
|
||||
else if (newValue == statisticsTab)
|
||||
navigation.navigateTo(MainView.class, MarketView.class, MarketsStatisticsView.class);
|
||||
navigation.navigateTo(MainView.class, MarketView.class, SpreadView.class);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -69,11 +69,11 @@ public class MarketView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
navigation.addListener(navigationListener);
|
||||
|
||||
if (root.getSelectionModel().getSelectedItem() == chartsTab)
|
||||
navigation.navigateTo(MainView.class, MarketView.class, MarketsChartsView.class);
|
||||
navigation.navigateTo(MainView.class, MarketView.class, OfferBookChartView.class);
|
||||
else if (root.getSelectionModel().getSelectedItem() == tradesTab)
|
||||
navigation.navigateTo(MainView.class, MarketView.class, TradesChartsView.class);
|
||||
else
|
||||
navigation.navigateTo(MainView.class, MarketView.class, MarketsStatisticsView.class);
|
||||
navigation.navigateTo(MainView.class, MarketView.class, SpreadView.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,9 +86,9 @@ public class MarketView extends ActivatableViewAndModel<TabPane, Activatable> {
|
|||
final Tab tab;
|
||||
View view = viewLoader.load(viewClass);
|
||||
|
||||
if (view instanceof MarketsChartsView) tab = chartsTab;
|
||||
if (view instanceof OfferBookChartView) tab = chartsTab;
|
||||
else if (view instanceof TradesChartsView) tab = tradesTab;
|
||||
else if (view instanceof MarketsStatisticsView) tab = statisticsTab;
|
||||
else if (view instanceof SpreadView) tab = statisticsTab;
|
||||
else throw new IllegalArgumentException("Navigation to " + viewClass + " is not supported");
|
||||
|
||||
tab.setContent(view.getRoot());
|
|
@ -0,0 +1,32 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
~ This file is part of Bitsquare.
|
||||
~
|
||||
~ Bitsquare is free software: you can redistribute it and/or modify it
|
||||
~ under the terms of the GNU Affero General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or (at
|
||||
~ your option) any later version.
|
||||
~
|
||||
~ Bitsquare 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 Affero General Public
|
||||
~ License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Affero General Public License
|
||||
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.market.offerbook.OfferBookChartView"
|
||||
spacing="20.0" fillWidth="true"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="20.0" top="10.0" right="20"/>
|
||||
</padding>
|
||||
|
||||
</VBox>
|
|
@ -15,7 +15,7 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.charts;
|
||||
package io.bitsquare.gui.main.market.offerbook;
|
||||
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
|
@ -27,7 +27,10 @@ import io.bitsquare.gui.main.offer.BuyOfferView;
|
|||
import io.bitsquare.gui.main.offer.SellOfferView;
|
||||
import io.bitsquare.gui.main.offer.offerbook.OfferBookListItem;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.locale.*;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
@ -45,7 +48,6 @@ import javafx.scene.image.ImageView;
|
|||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
import org.fxmisc.easybind.EasyBind;
|
||||
import org.fxmisc.easybind.Subscription;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -54,8 +56,8 @@ import org.slf4j.LoggerFactory;
|
|||
import javax.inject.Inject;
|
||||
|
||||
@FxmlView
|
||||
public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChartsViewModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(MarketsChartsView.class);
|
||||
public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookChartViewModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(OfferBookChartView.class);
|
||||
|
||||
private NumberAxis xAxis, yAxis;
|
||||
XYChart.Series seriesBuy, seriesSell;
|
||||
|
@ -71,6 +73,8 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
|||
private final StringProperty volumeColumnLabel = new SimpleStringProperty();
|
||||
private Button buyOfferButton;
|
||||
private Button sellOfferButton;
|
||||
private ChangeListener<Number> selectedTabIndexListener;
|
||||
private SingleSelectionModel<Tab> tabPaneSelectionModel;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -78,7 +82,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public MarketsChartsView(MarketsChartsViewModel model, Navigation navigation, BSFormatter formatter) {
|
||||
public OfferBookChartView(OfferBookChartViewModel model, Navigation navigation, BSFormatter formatter) {
|
||||
super(model);
|
||||
this.navigation = navigation;
|
||||
this.formatter = formatter;
|
||||
|
@ -90,24 +94,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
|||
public void initialize() {
|
||||
currencyComboBox = new ComboBox<>();
|
||||
currencyComboBox.setPromptText("Select currency");
|
||||
currencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
||||
@Override
|
||||
public String toString(TradeCurrency tradeCurrency) {
|
||||
// http://boschista.deviantart.com/journal/Cool-ASCII-Symbols-214218618
|
||||
if (tradeCurrency instanceof FiatCurrency)
|
||||
return "★ " + tradeCurrency.getNameAndCode();
|
||||
else if (tradeCurrency instanceof CryptoCurrency)
|
||||
return "✦ " + tradeCurrency.getNameAndCode();
|
||||
else
|
||||
return "-";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeCurrency fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
currencyComboBox.setConverter(GUIUtil.getCurrencyListConverter());
|
||||
|
||||
Label currencyLabel = new Label("Currency:");
|
||||
HBox currencyHBox = new HBox();
|
||||
|
@ -135,8 +122,15 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
|||
|
||||
@Override
|
||||
protected void activate() {
|
||||
// root.getParent() is null at initialize
|
||||
tabPaneSelectionModel = ((TabPane) root.getParent().getParent()).getSelectionModel();
|
||||
selectedTabIndexListener = (observable, oldValue, newValue) -> model.setSelectedTabIndex((int) newValue);
|
||||
|
||||
model.setSelectedTabIndex(tabPaneSelectionModel.getSelectedIndex());
|
||||
tabPaneSelectionModel.selectedIndexProperty().addListener(selectedTabIndexListener);
|
||||
|
||||
currencyComboBox.setItems(model.getTradeCurrencies());
|
||||
currencyComboBox.getSelectionModel().select(model.getTradeCurrency());
|
||||
currencyComboBox.getSelectionModel().select(model.getSelectedTradeCurrencyProperty());
|
||||
currencyComboBox.setVisibleRowCount(Math.min(currencyComboBox.getItems().size(), 25));
|
||||
currencyComboBox.setOnAction(e -> {
|
||||
TradeCurrency tradeCurrency = currencyComboBox.getSelectionModel().getSelectedItem();
|
||||
|
@ -145,7 +139,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
|||
});
|
||||
|
||||
model.getOfferBookListItems().addListener(changeListener);
|
||||
tradeCurrencySubscriber = EasyBind.subscribe(model.tradeCurrency,
|
||||
tradeCurrencySubscriber = EasyBind.subscribe(model.selectedTradeCurrencyProperty,
|
||||
tradeCurrency -> {
|
||||
String code = tradeCurrency.getCode();
|
||||
String tradeCurrencyName = tradeCurrency.getName();
|
||||
|
@ -173,6 +167,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
|||
@Override
|
||||
protected void deactivate() {
|
||||
model.getOfferBookListItems().removeListener(changeListener);
|
||||
tabPaneSelectionModel.selectedIndexProperty().removeListener(selectedTabIndexListener);
|
||||
tradeCurrencySubscriber.unsubscribe();
|
||||
currencyComboBox.setOnAction(null);
|
||||
}
|
|
@ -15,14 +15,20 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.charts;
|
||||
package io.bitsquare.gui.main.market.offerbook;
|
||||
|
||||
import com.google.common.math.LongMath;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.btc.pricefeed.PriceFeedService;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.ActivatableViewModel;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.offer.offerbook.OfferBook;
|
||||
import io.bitsquare.gui.main.offer.offerbook.OfferBookListItem;
|
||||
import io.bitsquare.gui.main.settings.SettingsView;
|
||||
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.CryptoCurrency;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
|
@ -44,16 +50,17 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class MarketsChartsViewModel extends ActivatableViewModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(MarketsChartsViewModel.class);
|
||||
class OfferBookChartViewModel extends ActivatableViewModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(OfferBookChartViewModel.class);
|
||||
|
||||
final static String EDIT_FLAG = "EDIT_FLAG";
|
||||
private static final int TAB_INDEX = 0;
|
||||
|
||||
private final OfferBook offerBook;
|
||||
private final Preferences preferences;
|
||||
final PriceFeedService priceFeedService;
|
||||
private Navigation navigation;
|
||||
|
||||
final ObjectProperty<TradeCurrency> tradeCurrency = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<TradeCurrency> selectedTradeCurrencyProperty = new SimpleObjectProperty<>();
|
||||
private final List<XYChart.Data> buyData = new ArrayList<>();
|
||||
private final List<XYChart.Data> sellData = new ArrayList<>();
|
||||
private final ObservableList<OfferBookListItem> offerBookListItems;
|
||||
|
@ -61,22 +68,25 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
private final ObservableList<Offer> top3BuyOfferList = FXCollections.observableArrayList();
|
||||
private final ObservableList<Offer> top3SellOfferList = FXCollections.observableArrayList();
|
||||
private final ChangeListener<Number> currenciesUpdatedListener;
|
||||
private int selectedTabIndex;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, lifecycle
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public MarketsChartsViewModel(OfferBook offerBook, Preferences preferences, PriceFeedService priceFeedService) {
|
||||
public OfferBookChartViewModel(OfferBook offerBook, Preferences preferences, PriceFeedService priceFeedService, Navigation navigation) {
|
||||
this.offerBook = offerBook;
|
||||
this.preferences = preferences;
|
||||
this.priceFeedService = priceFeedService;
|
||||
this.navigation = navigation;
|
||||
|
||||
Optional<TradeCurrency> tradeCurrencyOptional = CurrencyUtil.getTradeCurrency(preferences.getMarketScreenCurrencyCode());
|
||||
Optional<TradeCurrency> tradeCurrencyOptional = CurrencyUtil.getTradeCurrency(preferences.getOfferBookChartScreenCurrencyCode());
|
||||
if (tradeCurrencyOptional.isPresent())
|
||||
tradeCurrency.set(tradeCurrencyOptional.get());
|
||||
selectedTradeCurrencyProperty.set(tradeCurrencyOptional.get());
|
||||
else {
|
||||
tradeCurrency.set(CurrencyUtil.getDefaultTradeCurrency());
|
||||
selectedTradeCurrencyProperty.set(CurrencyUtil.getDefaultTradeCurrency());
|
||||
}
|
||||
|
||||
offerBookListItems = offerBook.getOfferBookListItems();
|
||||
|
@ -87,7 +97,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
list.addAll(c.getAddedSubList());
|
||||
if (list.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode()))
|
||||
.filter(e -> e.getCurrencyCode().equals(selectedTradeCurrencyProperty.get().getCode()))
|
||||
.findAny()
|
||||
.isPresent())
|
||||
updateChartData();
|
||||
|
@ -117,8 +127,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
if (isAnyPricePresent())
|
||||
priceFeedService.currenciesUpdateFlagProperty().addListener(currenciesUpdatedListener);
|
||||
|
||||
if (!preferences.getUseStickyMarketPrice())
|
||||
priceFeedService.setCurrencyCode(tradeCurrency.get().getCode());
|
||||
syncPriceFeedCurrency();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -126,6 +135,83 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
offerBookListItems.removeListener(listChangeListener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
|
||||
if (tradeCurrency != null) {
|
||||
final String code = tradeCurrency.getCode();
|
||||
|
||||
if (isEditEntry(code)) {
|
||||
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
||||
} else {
|
||||
selectedTradeCurrencyProperty.set(tradeCurrency);
|
||||
preferences.setOfferBookChartScreenCurrencyCode(code);
|
||||
|
||||
updateChartData();
|
||||
|
||||
if (!preferences.getUseStickyMarketPrice())
|
||||
priceFeedService.setCurrencyCode(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setSelectedTabIndex(int selectedTabIndex) {
|
||||
this.selectedTabIndex = selectedTabIndex;
|
||||
syncPriceFeedCurrency();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<XYChart.Data> getBuyData() {
|
||||
return buyData;
|
||||
}
|
||||
|
||||
public List<XYChart.Data> getSellData() {
|
||||
return sellData;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return selectedTradeCurrencyProperty.get().getCode();
|
||||
}
|
||||
|
||||
public ObservableList<OfferBookListItem> getOfferBookListItems() {
|
||||
return offerBookListItems;
|
||||
}
|
||||
|
||||
public ObservableList<Offer> getTop3BuyOfferList() {
|
||||
return top3BuyOfferList;
|
||||
}
|
||||
|
||||
public ObservableList<Offer> getTop3SellOfferList() {
|
||||
return top3SellOfferList;
|
||||
}
|
||||
|
||||
public ObservableList<TradeCurrency> getTradeCurrencies() {
|
||||
final ObservableList<TradeCurrency> list = FXCollections.observableArrayList(preferences.getTradeCurrenciesAsObservable());
|
||||
list.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, GUIUtil.EDIT_FLAG));
|
||||
return list;
|
||||
}
|
||||
|
||||
public TradeCurrency getSelectedTradeCurrencyProperty() {
|
||||
return selectedTradeCurrencyProperty.get();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void syncPriceFeedCurrency() {
|
||||
if (!preferences.getUseStickyMarketPrice() && selectedTabIndex == TAB_INDEX)
|
||||
priceFeedService.setCurrencyCode(selectedTradeCurrencyProperty.get().getCode());
|
||||
}
|
||||
|
||||
private boolean isAnyPricePresent() {
|
||||
return offerBookListItems.stream().filter(item -> item.getOffer().getPrice() == null).findAny().isPresent();
|
||||
}
|
||||
|
@ -133,7 +219,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
private void updateChartData() {
|
||||
List<Offer> allBuyOffers = offerBookListItems.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode())
|
||||
.filter(e -> e.getCurrencyCode().equals(selectedTradeCurrencyProperty.get().getCode())
|
||||
&& e.getDirection().equals(Offer.Direction.BUY))
|
||||
.sorted((o1, o2) -> {
|
||||
long a = o1.getPrice() != null ? o1.getPrice().value : 0;
|
||||
|
@ -148,7 +234,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
|
||||
List<Offer> allSellOffers = offerBookListItems.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode())
|
||||
.filter(e -> e.getCurrencyCode().equals(selectedTradeCurrencyProperty.get().getCode())
|
||||
&& e.getDirection().equals(Offer.Direction.SELL))
|
||||
.sorted((o1, o2) -> {
|
||||
long a = o1.getPrice() != null ? o1.getPrice().value : 0;
|
||||
|
@ -179,54 +265,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
|
||||
this.tradeCurrency.set(tradeCurrency);
|
||||
updateChartData();
|
||||
|
||||
if (!preferences.getUseStickyMarketPrice())
|
||||
priceFeedService.setCurrencyCode(tradeCurrency.getCode());
|
||||
|
||||
preferences.setMarketScreenCurrencyCode(tradeCurrency.getCode());
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<XYChart.Data> getBuyData() {
|
||||
return buyData;
|
||||
}
|
||||
|
||||
public List<XYChart.Data> getSellData() {
|
||||
return sellData;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return tradeCurrency.get().getCode();
|
||||
}
|
||||
|
||||
public ObservableList<OfferBookListItem> getOfferBookListItems() {
|
||||
return offerBookListItems;
|
||||
}
|
||||
|
||||
public ObservableList<Offer> getTop3BuyOfferList() {
|
||||
return top3BuyOfferList;
|
||||
}
|
||||
|
||||
public ObservableList<Offer> getTop3SellOfferList() {
|
||||
return top3SellOfferList;
|
||||
}
|
||||
|
||||
public ObservableList<TradeCurrency> getTradeCurrencies() {
|
||||
return preferences.getTradeCurrenciesAsObservable();
|
||||
}
|
||||
|
||||
public TradeCurrency getTradeCurrency() {
|
||||
return tradeCurrency.get();
|
||||
private boolean isEditEntry(String id) {
|
||||
return id.equals(GUIUtil.EDIT_FLAG);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package io.bitsquare.gui.main.markets.statistics;
|
||||
package io.bitsquare.gui.main.market.spread;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
|
@ -7,8 +7,8 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class MarketStatisticItem {
|
||||
private static final Logger log = LoggerFactory.getLogger(MarketStatisticItem.class);
|
||||
public class SpreadItem {
|
||||
private static final Logger log = LoggerFactory.getLogger(SpreadItem.class);
|
||||
public final String currencyCode;
|
||||
public final int numberOfBuyOffers;
|
||||
public final int numberOfSellOffers;
|
||||
|
@ -17,7 +17,7 @@ public class MarketStatisticItem {
|
|||
public final Fiat spread;
|
||||
public final Coin totalAmount;
|
||||
|
||||
public MarketStatisticItem(String currencyCode, int numberOfBuyOffers, int numberOfSellOffers, int numberOfOffers, @Nullable Fiat spread, Coin totalAmount) {
|
||||
public SpreadItem(String currencyCode, int numberOfBuyOffers, int numberOfSellOffers, int numberOfOffers, @Nullable Fiat spread, Coin totalAmount) {
|
||||
this.currencyCode = currencyCode;
|
||||
this.numberOfBuyOffers = numberOfBuyOffers;
|
||||
this.numberOfSellOffers = numberOfSellOffers;
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.markets.statistics.MarketsStatisticsView"
|
||||
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.market.spread.SpreadView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
|
@ -15,7 +15,7 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.statistics;
|
||||
package io.bitsquare.gui.main.market.spread;
|
||||
|
||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
|
@ -38,13 +38,13 @@ import org.bitcoinj.core.Coin;
|
|||
import javax.inject.Inject;
|
||||
|
||||
@FxmlView
|
||||
public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, MarketsStatisticViewModel> {
|
||||
public class SpreadView extends ActivatableViewAndModel<GridPane, SpreadViewModel> {
|
||||
private final BSFormatter formatter;
|
||||
private final int gridRow = 0;
|
||||
private TableView<MarketStatisticItem> tableView;
|
||||
private SortedList<MarketStatisticItem> sortedList;
|
||||
private ListChangeListener<MarketStatisticItem> itemListChangeListener;
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> totalAmountColumn, numberOfOffersColumn, numberOfBuyOffersColumn, numberOfSellOffersColumn;
|
||||
private TableView<SpreadItem> tableView;
|
||||
private SortedList<SpreadItem> sortedList;
|
||||
private ListChangeListener<SpreadItem> itemListChangeListener;
|
||||
private TableColumn<SpreadItem, SpreadItem> totalAmountColumn, numberOfOffersColumn, numberOfBuyOffersColumn, numberOfSellOffersColumn;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -52,7 +52,7 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public MarketsStatisticsView(MarketsStatisticViewModel model, BSFormatter formatter) {
|
||||
public SpreadView(SpreadViewModel model, BSFormatter formatter) {
|
||||
super(model);
|
||||
this.formatter = formatter;
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
placeholder.setWrapText(true);
|
||||
tableView.setPlaceholder(placeholder);
|
||||
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> currencyColumn = getCurrencyColumn();
|
||||
TableColumn<SpreadItem, SpreadItem> currencyColumn = getCurrencyColumn();
|
||||
tableView.getColumns().add(currencyColumn);
|
||||
numberOfOffersColumn = getNumberOfOffersColumn();
|
||||
tableView.getColumns().add(numberOfOffersColumn);
|
||||
|
@ -84,7 +84,7 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
tableView.getColumns().add(numberOfSellOffersColumn);
|
||||
totalAmountColumn = getTotalAmountColumn();
|
||||
tableView.getColumns().add(totalAmountColumn);
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> spreadColumn = getSpreadColumn();
|
||||
TableColumn<SpreadItem, SpreadItem> spreadColumn = getSpreadColumn();
|
||||
tableView.getColumns().add(spreadColumn);
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
|
||||
@Override
|
||||
protected void activate() {
|
||||
sortedList = new SortedList<>(model.marketStatisticItems);
|
||||
sortedList = new SortedList<>(model.spreadItems);
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
tableView.setItems(sortedList);
|
||||
sortedList.addListener(itemListChangeListener);
|
||||
|
@ -127,22 +127,22 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
// Columns
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> getCurrencyColumn() {
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column = new TableColumn<MarketStatisticItem, MarketStatisticItem>("Currency") {
|
||||
private TableColumn<SpreadItem, SpreadItem> getCurrencyColumn() {
|
||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Currency") {
|
||||
{
|
||||
setMinWidth(100);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<MarketStatisticItem, MarketStatisticItem>, TableCell<MarketStatisticItem,
|
||||
MarketStatisticItem>>() {
|
||||
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
|
||||
SpreadItem>>() {
|
||||
@Override
|
||||
public TableCell<MarketStatisticItem, MarketStatisticItem> call(
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column) {
|
||||
return new TableCell<MarketStatisticItem, MarketStatisticItem>() {
|
||||
public TableCell<SpreadItem, SpreadItem> call(
|
||||
TableColumn<SpreadItem, SpreadItem> column) {
|
||||
return new TableCell<SpreadItem, SpreadItem>() {
|
||||
@Override
|
||||
public void updateItem(final MarketStatisticItem item, boolean empty) {
|
||||
public void updateItem(final SpreadItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
setText(CurrencyUtil.getNameByCode(item.currencyCode));
|
||||
|
@ -155,22 +155,22 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
return column;
|
||||
}
|
||||
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> getNumberOfOffersColumn() {
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column = new TableColumn<MarketStatisticItem, MarketStatisticItem>("Total offers") {
|
||||
private TableColumn<SpreadItem, SpreadItem> getNumberOfOffersColumn() {
|
||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Total offers") {
|
||||
{
|
||||
setMinWidth(100);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<MarketStatisticItem, MarketStatisticItem>, TableCell<MarketStatisticItem,
|
||||
MarketStatisticItem>>() {
|
||||
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
|
||||
SpreadItem>>() {
|
||||
@Override
|
||||
public TableCell<MarketStatisticItem, MarketStatisticItem> call(
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column) {
|
||||
return new TableCell<MarketStatisticItem, MarketStatisticItem>() {
|
||||
public TableCell<SpreadItem, SpreadItem> call(
|
||||
TableColumn<SpreadItem, SpreadItem> column) {
|
||||
return new TableCell<SpreadItem, SpreadItem>() {
|
||||
@Override
|
||||
public void updateItem(final MarketStatisticItem item, boolean empty) {
|
||||
public void updateItem(final SpreadItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
setText(String.valueOf(item.numberOfOffers));
|
||||
|
@ -183,22 +183,22 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
return column;
|
||||
}
|
||||
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> getNumberOfBuyOffersColumn() {
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column = new TableColumn<MarketStatisticItem, MarketStatisticItem>("Buy offers") {
|
||||
private TableColumn<SpreadItem, SpreadItem> getNumberOfBuyOffersColumn() {
|
||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Buy offers") {
|
||||
{
|
||||
setMinWidth(100);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<MarketStatisticItem, MarketStatisticItem>, TableCell<MarketStatisticItem,
|
||||
MarketStatisticItem>>() {
|
||||
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
|
||||
SpreadItem>>() {
|
||||
@Override
|
||||
public TableCell<MarketStatisticItem, MarketStatisticItem> call(
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column) {
|
||||
return new TableCell<MarketStatisticItem, MarketStatisticItem>() {
|
||||
public TableCell<SpreadItem, SpreadItem> call(
|
||||
TableColumn<SpreadItem, SpreadItem> column) {
|
||||
return new TableCell<SpreadItem, SpreadItem>() {
|
||||
@Override
|
||||
public void updateItem(final MarketStatisticItem item, boolean empty) {
|
||||
public void updateItem(final SpreadItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
setText(String.valueOf(item.numberOfBuyOffers));
|
||||
|
@ -211,22 +211,22 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
return column;
|
||||
}
|
||||
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> getNumberOfSellOffersColumn() {
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column = new TableColumn<MarketStatisticItem, MarketStatisticItem>("Sell offers") {
|
||||
private TableColumn<SpreadItem, SpreadItem> getNumberOfSellOffersColumn() {
|
||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Sell offers") {
|
||||
{
|
||||
setMinWidth(100);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<MarketStatisticItem, MarketStatisticItem>, TableCell<MarketStatisticItem,
|
||||
MarketStatisticItem>>() {
|
||||
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
|
||||
SpreadItem>>() {
|
||||
@Override
|
||||
public TableCell<MarketStatisticItem, MarketStatisticItem> call(
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column) {
|
||||
return new TableCell<MarketStatisticItem, MarketStatisticItem>() {
|
||||
public TableCell<SpreadItem, SpreadItem> call(
|
||||
TableColumn<SpreadItem, SpreadItem> column) {
|
||||
return new TableCell<SpreadItem, SpreadItem>() {
|
||||
@Override
|
||||
public void updateItem(final MarketStatisticItem item, boolean empty) {
|
||||
public void updateItem(final SpreadItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
setText(String.valueOf(item.numberOfSellOffers));
|
||||
|
@ -239,22 +239,22 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
return column;
|
||||
}
|
||||
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> getTotalAmountColumn() {
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column = new TableColumn<MarketStatisticItem, MarketStatisticItem>("Total amount") {
|
||||
private TableColumn<SpreadItem, SpreadItem> getTotalAmountColumn() {
|
||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Total amount") {
|
||||
{
|
||||
setMinWidth(150);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<MarketStatisticItem, MarketStatisticItem>, TableCell<MarketStatisticItem,
|
||||
MarketStatisticItem>>() {
|
||||
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
|
||||
SpreadItem>>() {
|
||||
@Override
|
||||
public TableCell<MarketStatisticItem, MarketStatisticItem> call(
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column) {
|
||||
return new TableCell<MarketStatisticItem, MarketStatisticItem>() {
|
||||
public TableCell<SpreadItem, SpreadItem> call(
|
||||
TableColumn<SpreadItem, SpreadItem> column) {
|
||||
return new TableCell<SpreadItem, SpreadItem>() {
|
||||
@Override
|
||||
public void updateItem(final MarketStatisticItem item, boolean empty) {
|
||||
public void updateItem(final SpreadItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
setText(formatter.formatCoin(item.totalAmount));
|
||||
|
@ -267,22 +267,22 @@ public class MarketsStatisticsView extends ActivatableViewAndModel<GridPane, Mar
|
|||
return column;
|
||||
}
|
||||
|
||||
private TableColumn<MarketStatisticItem, MarketStatisticItem> getSpreadColumn() {
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column = new TableColumn<MarketStatisticItem, MarketStatisticItem>("Spread") {
|
||||
private TableColumn<SpreadItem, SpreadItem> getSpreadColumn() {
|
||||
TableColumn<SpreadItem, SpreadItem> column = new TableColumn<SpreadItem, SpreadItem>("Spread") {
|
||||
{
|
||||
setMinWidth(130);
|
||||
}
|
||||
};
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<MarketStatisticItem, MarketStatisticItem>, TableCell<MarketStatisticItem,
|
||||
MarketStatisticItem>>() {
|
||||
new Callback<TableColumn<SpreadItem, SpreadItem>, TableCell<SpreadItem,
|
||||
SpreadItem>>() {
|
||||
@Override
|
||||
public TableCell<MarketStatisticItem, MarketStatisticItem> call(
|
||||
TableColumn<MarketStatisticItem, MarketStatisticItem> column) {
|
||||
return new TableCell<MarketStatisticItem, MarketStatisticItem>() {
|
||||
public TableCell<SpreadItem, SpreadItem> call(
|
||||
TableColumn<SpreadItem, SpreadItem> column) {
|
||||
return new TableCell<SpreadItem, SpreadItem>() {
|
||||
@Override
|
||||
public void updateItem(final MarketStatisticItem item, boolean empty) {
|
||||
public void updateItem(final SpreadItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (item.spread != null)
|
|
@ -15,7 +15,7 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.statistics;
|
||||
package io.bitsquare.gui.main.market.spread;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.gui.common.model.ActivatableViewModel;
|
||||
|
@ -34,12 +34,12 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
class MarketsStatisticViewModel extends ActivatableViewModel {
|
||||
class SpreadViewModel extends ActivatableViewModel {
|
||||
|
||||
private final OfferBook offerBook;
|
||||
private final ObservableList<OfferBookListItem> offerBookListItems;
|
||||
private final ListChangeListener<OfferBookListItem> listChangeListener;
|
||||
final ObservableList<MarketStatisticItem> marketStatisticItems = FXCollections.observableArrayList();
|
||||
final ObservableList<SpreadItem> spreadItems = FXCollections.observableArrayList();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -47,7 +47,7 @@ class MarketsStatisticViewModel extends ActivatableViewModel {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public MarketsStatisticViewModel(OfferBook offerBook) {
|
||||
public SpreadViewModel(OfferBook offerBook) {
|
||||
this.offerBook = offerBook;
|
||||
|
||||
offerBookListItems = offerBook.getOfferBookListItems();
|
||||
|
@ -75,7 +75,7 @@ class MarketsStatisticViewModel extends ActivatableViewModel {
|
|||
offersByCurrencyMap.put(currencyCode, new ArrayList<>());
|
||||
offersByCurrencyMap.get(currencyCode).add(offer);
|
||||
}
|
||||
marketStatisticItems.clear();
|
||||
spreadItems.clear();
|
||||
for (String currencyCode : offersByCurrencyMap.keySet()) {
|
||||
List<Offer> offers = offersByCurrencyMap.get(currencyCode);
|
||||
List<Offer> buyOffers = offers
|
||||
|
@ -109,7 +109,7 @@ class MarketsStatisticViewModel extends ActivatableViewModel {
|
|||
spread = bestSellOfferPrice.subtract(bestBuyOfferPrice);
|
||||
|
||||
Coin totalAmount = Coin.valueOf(offers.stream().mapToLong(offer -> offer.getAmount().getValue()).sum());
|
||||
marketStatisticItems.add(new MarketStatisticItem(currencyCode, buyOffers.size(), sellOffers.size(), offers.size(), spread, totalAmount));
|
||||
spreadItems.add(new SpreadItem(currencyCode, buyOffers.size(), sellOffers.size(), offers.size(), spread, totalAmount));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.markets.trades.TradesChartsView"
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.market.trades.TradesChartsView"
|
||||
spacing="10.0" fillWidth="true"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
|
@ -15,16 +15,15 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.trades;
|
||||
package io.bitsquare.gui.main.market.trades;
|
||||
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||
import io.bitsquare.gui.common.view.FxmlView;
|
||||
import io.bitsquare.gui.main.markets.trades.charts.price.CandleStickChart;
|
||||
import io.bitsquare.gui.main.markets.trades.charts.volume.VolumeChart;
|
||||
import io.bitsquare.gui.main.market.trades.charts.price.CandleStickChart;
|
||||
import io.bitsquare.gui.main.market.trades.charts.volume.VolumeChart;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.locale.CryptoCurrency;
|
||||
import io.bitsquare.locale.FiatCurrency;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.trade.statistics.TradeStatistics;
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
|
@ -81,6 +80,11 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
private SortedList<TradeStatistics> sortedList;
|
||||
private Label nrOfTradeStatisticsLabel;
|
||||
private ListChangeListener<TradeStatistics> tradeStatisticsByCurrencyListener;
|
||||
private TableColumn<TradeStatistics, TradeStatistics> priceColumn;
|
||||
private ChangeListener<Number> selectedTabIndexListener;
|
||||
private SingleSelectionModel<Tab> tabPaneSelectionModel;
|
||||
private ChangeListener<Boolean> showAllTradeCurrenciesListener;
|
||||
private TableColumn<TradeStatistics, TradeStatistics> volumeColumn;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -122,12 +126,30 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
layoutChart();
|
||||
};
|
||||
tradeStatisticsByCurrencyListener = c -> nrOfTradeStatisticsLabel.setText("Nr. of trades: " + model.tradeStatisticsByCurrency.size());
|
||||
showAllTradeCurrenciesListener = (observable, oldValue, newValue) -> {
|
||||
priceChart.setVisible(!newValue);
|
||||
priceChart.setManaged(!newValue);
|
||||
priceColumn.setSortable(!newValue);
|
||||
priceColumnLabel.set("Price" + (newValue ? "" : (" (" + model.getCurrencyCode() + ")")));
|
||||
volumeColumn.setText("Volume" + (newValue ? "" : (" (" + model.getCurrencyCode() + ")")));
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
// root.getParent() is null at initialize
|
||||
tabPaneSelectionModel = ((TabPane) root.getParent().getParent()).getSelectionModel();
|
||||
selectedTabIndexListener = (observable, oldValue, newValue) -> model.setSelectedTabIndex((int) newValue);
|
||||
model.setSelectedTabIndex(tabPaneSelectionModel.getSelectedIndex());
|
||||
tabPaneSelectionModel.selectedIndexProperty().addListener(selectedTabIndexListener);
|
||||
|
||||
currencyComboBox.setItems(model.getTradeCurrencies());
|
||||
currencyComboBox.getSelectionModel().select(model.getTradeCurrency());
|
||||
|
||||
if (model.showAllTradeCurrenciesProperty.get())
|
||||
currencyComboBox.getSelectionModel().select(0);
|
||||
else
|
||||
currencyComboBox.getSelectionModel().select(model.getSelectedTradeCurrency());
|
||||
|
||||
currencyComboBox.setVisibleRowCount(Math.min(currencyComboBox.getItems().size(), 25));
|
||||
currencyComboBox.setOnAction(e -> model.onSetTradeCurrency(currencyComboBox.getSelectionModel().getSelectedItem()));
|
||||
|
||||
|
@ -137,15 +159,22 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
toggleGroup.selectedToggleProperty().addListener(toggleChangeListener);
|
||||
priceAxisY.widthProperty().addListener(priceAxisYWidthListener);
|
||||
volumeAxisY.widthProperty().addListener(volumeAxisYWidthListener);
|
||||
model.tradeStatisticsByCurrency.addListener(tradeStatisticsByCurrencyListener);
|
||||
model.showAllTradeCurrenciesProperty.addListener(showAllTradeCurrenciesListener);
|
||||
|
||||
tradeCurrencySubscriber = EasyBind.subscribe(model.tradeCurrencyProperty,
|
||||
priceAxisY.labelProperty().bind(priceColumnLabel);
|
||||
priceColumn.textProperty().bind(priceColumnLabel);
|
||||
|
||||
tradeCurrencySubscriber = EasyBind.subscribe(model.selectedTradeCurrencyProperty,
|
||||
tradeCurrency -> {
|
||||
String code = tradeCurrency.getCode();
|
||||
String tradeCurrencyName = tradeCurrency.getName();
|
||||
|
||||
priceSeries.setName(tradeCurrencyName);
|
||||
final String currencyPair = formatter.getCurrencyPair(code);
|
||||
priceColumnLabel.set("Price (" + currencyPair + ")");
|
||||
final boolean showAllTradeCurrencies = model.showAllTradeCurrenciesProperty.get();
|
||||
priceColumnLabel.set("Price" + (showAllTradeCurrencies ? "" : (" (" + currencyPair + ")")));
|
||||
volumeColumn.setText("Volume" + (showAllTradeCurrencies ? "" : (" (" + code + ")")));
|
||||
});
|
||||
|
||||
sortedList = new SortedList<>(model.tradeStatisticsByCurrency);
|
||||
|
@ -158,23 +187,30 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
priceAxisX.setTickLabelFormatter(getTimeAxisStringConverter());
|
||||
volumeAxisX.setTickLabelFormatter(getTimeAxisStringConverter());
|
||||
|
||||
model.tradeStatisticsByCurrency.addListener(tradeStatisticsByCurrencyListener);
|
||||
nrOfTradeStatisticsLabel.setText("Nr. of trades: " + model.tradeStatisticsByCurrency.size());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
currencyComboBox.setOnAction(null);
|
||||
|
||||
tabPaneSelectionModel.selectedIndexProperty().removeListener(selectedTabIndexListener);
|
||||
model.priceItems.removeListener(itemsChangeListener);
|
||||
toggleGroup.selectedToggleProperty().removeListener(toggleChangeListener);
|
||||
priceAxisY.widthProperty().removeListener(priceAxisYWidthListener);
|
||||
volumeAxisY.widthProperty().removeListener(volumeAxisYWidthListener);
|
||||
model.tradeStatisticsByCurrency.removeListener(tradeStatisticsByCurrencyListener);
|
||||
tradeCurrencySubscriber.unsubscribe();
|
||||
currencyComboBox.setOnAction(null);
|
||||
model.showAllTradeCurrenciesProperty.removeListener(showAllTradeCurrenciesListener);
|
||||
|
||||
priceAxisY.labelProperty().unbind();
|
||||
priceColumn.textProperty().unbind();
|
||||
|
||||
tradeCurrencySubscriber.unsubscribe();
|
||||
|
||||
sortedList.comparatorProperty().unbind();
|
||||
|
||||
priceSeries.getData().clear();
|
||||
priceChart.getData().clear();
|
||||
sortedList.comparatorProperty().unbind();
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,7 +230,6 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
priceAxisY = new NumberAxis();
|
||||
priceAxisY.setForceZeroInRange(false);
|
||||
priceAxisY.setAutoRanging(true);
|
||||
priceAxisY.labelProperty().bind(priceColumnLabel);
|
||||
priceAxisY.setTickLabelFormatter(new StringConverter<Number>() {
|
||||
@Override
|
||||
public String toString(Number object) {
|
||||
|
@ -207,11 +242,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
}
|
||||
});
|
||||
|
||||
priceChart = new CandleStickChart(priceAxisX, priceAxisY);
|
||||
priceChart.setMinHeight(250);
|
||||
priceChart.setLegendVisible(false);
|
||||
priceChart.setData(FXCollections.observableArrayList(priceSeries));
|
||||
priceChart.setToolTipStringConverter(new StringConverter<Number>() {
|
||||
priceChart = new CandleStickChart(priceAxisX, priceAxisY, new StringConverter<Number>() {
|
||||
@Override
|
||||
public String toString(Number object) {
|
||||
return formatter.formatFiatWithCode(Fiat.valueOf(model.getCurrencyCode(), (long) object));
|
||||
|
@ -222,6 +253,10 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
return null;
|
||||
}
|
||||
});
|
||||
priceChart.setMinHeight(250);
|
||||
priceChart.setMaxHeight(300);
|
||||
priceChart.setLegendVisible(false);
|
||||
priceChart.setData(FXCollections.observableArrayList(priceSeries));
|
||||
|
||||
|
||||
volumeSeries = new XYChart.Series<>();
|
||||
|
@ -248,14 +283,10 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
}
|
||||
});
|
||||
|
||||
volumeChart = new VolumeChart(volumeAxisX, volumeAxisY);
|
||||
volumeChart.setData(FXCollections.observableArrayList(volumeSeries));
|
||||
volumeChart.setMinHeight(140);
|
||||
volumeChart.setLegendVisible(false);
|
||||
volumeChart.setToolTipStringConverter(new StringConverter<Number>() {
|
||||
volumeChart = new VolumeChart(volumeAxisX, volumeAxisY, new StringConverter<Number>() {
|
||||
@Override
|
||||
public String toString(Number object) {
|
||||
return formatter.formatCoinWithCode(Coin.valueOf(new Double((double) object).longValue()));
|
||||
return formatter.formatCoinWithCode(Coin.valueOf((long) object));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -263,6 +294,10 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
return null;
|
||||
}
|
||||
});
|
||||
volumeChart.setData(FXCollections.observableArrayList(volumeSeries));
|
||||
volumeChart.setMinHeight(140);
|
||||
volumeChart.setMaxHeight(200);
|
||||
volumeChart.setLegendVisible(false);
|
||||
}
|
||||
|
||||
private void updateChartData() {
|
||||
|
@ -320,23 +355,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
|
||||
currencyComboBox = new ComboBox<>();
|
||||
currencyComboBox.setPromptText("Select currency");
|
||||
currencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
||||
@Override
|
||||
public String toString(TradeCurrency tradeCurrency) {
|
||||
// http://boschista.deviantart.com/journal/Cool-ASCII-Symbols-214218618
|
||||
if (tradeCurrency instanceof FiatCurrency)
|
||||
return "★ " + tradeCurrency.getNameAndCode();
|
||||
else if (tradeCurrency instanceof CryptoCurrency)
|
||||
return "✦ " + tradeCurrency.getNameAndCode();
|
||||
else
|
||||
return "-";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeCurrency fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
currencyComboBox.setConverter(GUIUtil.getCurrencyListConverter());
|
||||
|
||||
Pane spacer = new Pane();
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
|
@ -377,6 +396,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
private void createTable() {
|
||||
tableView = new TableView<>();
|
||||
tableView.setMinHeight(120);
|
||||
VBox.setVgrow(tableView, Priority.ALWAYS);
|
||||
|
||||
// date
|
||||
TableColumn<TradeStatistics, TradeStatistics> dateColumn = new TableColumn<>("Date/Time");
|
||||
|
@ -427,9 +447,8 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
tableView.getColumns().add(amountColumn);
|
||||
|
||||
// price
|
||||
TableColumn<TradeStatistics, TradeStatistics> priceColumn = new TableColumn<>();
|
||||
priceColumn = new TableColumn<>();
|
||||
priceColumn.setCellValueFactory((tradeStatistics) -> new ReadOnlyObjectWrapper<>(tradeStatistics.getValue()));
|
||||
priceColumn.textProperty().bind(priceColumnLabel);
|
||||
priceColumn.setCellFactory(
|
||||
new Callback<TableColumn<TradeStatistics, TradeStatistics>, TableCell<TradeStatistics,
|
||||
TradeStatistics>>() {
|
||||
|
@ -441,7 +460,9 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
public void updateItem(final TradeStatistics item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(formatter.formatFiat(item.getTradePrice()));
|
||||
setText(model.showAllTradeCurrenciesProperty.get() ?
|
||||
formatter.formatFiatWithCode(item.getTradePrice()) :
|
||||
formatter.formatFiat(item.getTradePrice()));
|
||||
else
|
||||
setText("");
|
||||
}
|
||||
|
@ -452,9 +473,8 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
tableView.getColumns().add(priceColumn);
|
||||
|
||||
// volume
|
||||
TableColumn<TradeStatistics, TradeStatistics> volumeColumn = new TableColumn<>();
|
||||
volumeColumn = new TableColumn<>();
|
||||
volumeColumn.setCellValueFactory((tradeStatistics) -> new ReadOnlyObjectWrapper<>(tradeStatistics.getValue()));
|
||||
volumeColumn.setText("Volume (BTC)");
|
||||
volumeColumn.setCellFactory(
|
||||
new Callback<TableColumn<TradeStatistics, TradeStatistics>, TableCell<TradeStatistics,
|
||||
TradeStatistics>>() {
|
||||
|
@ -466,7 +486,9 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
|
|||
public void updateItem(final TradeStatistics item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null)
|
||||
setText(formatter.formatFiatWithCode(item.getTradeVolume()));
|
||||
setText(model.showAllTradeCurrenciesProperty.get() ?
|
||||
formatter.formatFiatWithCode(item.getTradeVolume()) :
|
||||
formatter.formatFiat(item.getTradeVolume()));
|
||||
else
|
||||
setText("");
|
||||
}
|
|
@ -15,19 +15,28 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.trades;
|
||||
package io.bitsquare.gui.main.market.trades;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.inject.Inject;
|
||||
import io.bitsquare.btc.pricefeed.PriceFeedService;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.ActivatableViewModel;
|
||||
import io.bitsquare.gui.main.markets.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.settings.SettingsView;
|
||||
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.CryptoCurrency;
|
||||
import io.bitsquare.locale.CurrencyUtil;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.trade.statistics.TradeStatistics;
|
||||
import io.bitsquare.trade.statistics.TradeStatisticsManager;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
|
@ -42,6 +51,8 @@ import java.util.stream.Collectors;
|
|||
|
||||
class TradesChartsViewModel extends ActivatableViewModel {
|
||||
private static final Logger log = LoggerFactory.getLogger(TradesChartsViewModel.class);
|
||||
private static final int TAB_INDEX = 2;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Enum
|
||||
|
@ -59,9 +70,12 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
private final TradeStatisticsManager tradeStatisticsManager;
|
||||
final Preferences preferences;
|
||||
private PriceFeedService priceFeedService;
|
||||
private Navigation navigation;
|
||||
private BSFormatter formatter;
|
||||
|
||||
private final SetChangeListener<TradeStatistics> setChangeListener;
|
||||
final ObjectProperty<TradeCurrency> tradeCurrencyProperty = new SimpleObjectProperty<>();
|
||||
final ObjectProperty<TradeCurrency> selectedTradeCurrencyProperty = new SimpleObjectProperty<>();
|
||||
final BooleanProperty showAllTradeCurrenciesProperty = new SimpleBooleanProperty(false);
|
||||
|
||||
final ObservableList<TradeStatistics> tradeStatisticsByCurrency = FXCollections.observableArrayList();
|
||||
ObservableList<XYChart.Data<Number, Number>> priceItems = FXCollections.observableArrayList();
|
||||
|
@ -69,6 +83,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
|
||||
TickUnit tickUnit = TickUnit.MONTH;
|
||||
int maxTicks = 30;
|
||||
private int selectedTabIndex;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -76,19 +91,20 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
public TradesChartsViewModel(TradeStatisticsManager tradeStatisticsManager, Preferences preferences, PriceFeedService priceFeedService) {
|
||||
public TradesChartsViewModel(TradeStatisticsManager tradeStatisticsManager, Preferences preferences, PriceFeedService priceFeedService, Navigation navigation, BSFormatter formatter) {
|
||||
this.tradeStatisticsManager = tradeStatisticsManager;
|
||||
this.preferences = preferences;
|
||||
this.priceFeedService = priceFeedService;
|
||||
this.navigation = navigation;
|
||||
this.formatter = formatter;
|
||||
|
||||
setChangeListener = change -> updateChartData();
|
||||
|
||||
Optional<TradeCurrency> tradeCurrencyOptional = CurrencyUtil.getTradeCurrency(preferences.getTradeStatisticsScreenCurrencyCode());
|
||||
Optional<TradeCurrency> tradeCurrencyOptional = CurrencyUtil.getTradeCurrency(preferences.getTradeChartsScreenCurrencyCode());
|
||||
if (tradeCurrencyOptional.isPresent())
|
||||
tradeCurrencyProperty.set(tradeCurrencyOptional.get());
|
||||
else {
|
||||
tradeCurrencyProperty.set(CurrencyUtil.getDefaultTradeCurrency());
|
||||
}
|
||||
selectedTradeCurrencyProperty.set(tradeCurrencyOptional.get());
|
||||
else
|
||||
selectedTradeCurrencyProperty.set(CurrencyUtil.getDefaultTradeCurrency());
|
||||
|
||||
tickUnit = TickUnit.values()[preferences.getTradeStatisticsTickUnitIndex()];
|
||||
}
|
||||
|
@ -105,9 +121,8 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
protected void activate() {
|
||||
tradeStatisticsManager.getObservableTradeStatisticsSet().addListener(setChangeListener);
|
||||
updateChartData();
|
||||
|
||||
if (!preferences.getUseStickyMarketPrice())
|
||||
priceFeedService.setCurrencyCode(tradeCurrencyProperty.get().getCode());
|
||||
syncPriceFeedCurrency();
|
||||
setMarketPriceFeedCurrency();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -120,37 +135,62 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
|
||||
this.tradeCurrencyProperty.set(tradeCurrency);
|
||||
preferences.setTradeStatisticsScreenCurrencyCode(tradeCurrency.getCode());
|
||||
updateChartData();
|
||||
void onSetTradeCurrency(TradeCurrency tradeCurrency) {
|
||||
if (tradeCurrency != null) {
|
||||
final String code = tradeCurrency.getCode();
|
||||
|
||||
if (!preferences.getUseStickyMarketPrice())
|
||||
priceFeedService.setCurrencyCode(tradeCurrency.getCode());
|
||||
if (isEditEntry(code)) {
|
||||
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
||||
} else {
|
||||
boolean showAllEntry = isShowAllEntry(code);
|
||||
showAllTradeCurrenciesProperty.set(showAllEntry);
|
||||
if (!showAllEntry) {
|
||||
selectedTradeCurrencyProperty.set(tradeCurrency);
|
||||
preferences.setTradeChartsScreenCurrencyCode(code);
|
||||
}
|
||||
|
||||
updateChartData();
|
||||
|
||||
if (!preferences.getUseStickyMarketPrice()) {
|
||||
if (showAllEntry)
|
||||
priceFeedService.setCurrencyCode(CurrencyUtil.getDefaultTradeCurrency().getCode());
|
||||
else
|
||||
priceFeedService.setCurrencyCode(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTickUnit(TickUnit tickUnit) {
|
||||
void setTickUnit(TickUnit tickUnit) {
|
||||
this.tickUnit = tickUnit;
|
||||
preferences.setTradeStatisticsTickUnitIndex(tickUnit.ordinal());
|
||||
updateChartData();
|
||||
}
|
||||
|
||||
void setSelectedTabIndex(int selectedTabIndex) {
|
||||
this.selectedTabIndex = selectedTabIndex;
|
||||
syncPriceFeedCurrency();
|
||||
setMarketPriceFeedCurrency();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getters
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return tradeCurrencyProperty.get().getCode();
|
||||
return selectedTradeCurrencyProperty.get().getCode();
|
||||
}
|
||||
|
||||
public ObservableList<TradeCurrency> getTradeCurrencies() {
|
||||
return preferences.getTradeCurrenciesAsObservable();
|
||||
final ObservableList<TradeCurrency> list = FXCollections.observableArrayList(preferences.getTradeCurrenciesAsObservable());
|
||||
list.add(0, new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, GUIUtil.SHOW_ALL_FLAG));
|
||||
list.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, GUIUtil.EDIT_FLAG));
|
||||
return list;
|
||||
}
|
||||
|
||||
public TradeCurrency getTradeCurrency() {
|
||||
return tradeCurrencyProperty.get();
|
||||
public TradeCurrency getSelectedTradeCurrency() {
|
||||
return selectedTradeCurrencyProperty.get();
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,10 +198,23 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void setMarketPriceFeedCurrency() {
|
||||
if (!preferences.getUseStickyMarketPrice() && selectedTabIndex == TAB_INDEX) {
|
||||
if (showAllTradeCurrenciesProperty.get())
|
||||
priceFeedService.setCurrencyCode(CurrencyUtil.getDefaultTradeCurrency().getCode());
|
||||
else
|
||||
priceFeedService.setCurrencyCode(getCurrencyCode());
|
||||
}
|
||||
}
|
||||
|
||||
private void syncPriceFeedCurrency() {
|
||||
if (!preferences.getUseStickyMarketPrice() && selectedTabIndex == TAB_INDEX)
|
||||
priceFeedService.setCurrencyCode(selectedTradeCurrencyProperty.get().getCode());
|
||||
}
|
||||
|
||||
private void updateChartData() {
|
||||
tradeStatisticsByCurrency.setAll(tradeStatisticsManager.getObservableTradeStatisticsSet().stream()
|
||||
.filter(e -> e.currency.equals(getCurrencyCode()))
|
||||
.filter(e -> showAllTradeCurrenciesProperty.get() || e.currency.equals(getCurrencyCode()))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
// Get all entries for the defined time interval
|
||||
|
@ -183,6 +236,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
// create CandleData for defined time interval
|
||||
List<CandleData> candleDataList = itemsPerInterval.entrySet().stream()
|
||||
.map(entry -> getCandleData(entry.getKey(), entry.getValue()))
|
||||
.filter(e -> e.tick >= 0)
|
||||
.collect(Collectors.toList());
|
||||
candleDataList.sort((o1, o2) -> (o1.tick < o2.tick ? -1 : (o1.tick == o2.tick ? 0 : 1)));
|
||||
|
||||
|
@ -221,7 +275,12 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
close = list.get(list.size() - 1).tradePrice;
|
||||
}
|
||||
boolean isBullish = close > open;
|
||||
return new CandleData(tick, open, close, high, low, averagePrice, accumulatedAmount, accumulatedVolume, isBullish);
|
||||
final Date date = new Date(getTimeFromTickIndex(tick));
|
||||
String dateString = tickUnit.ordinal() > TickUnit.DAY.ordinal() ?
|
||||
formatter.formatDateTime(date) :
|
||||
formatter.formatDate(date);
|
||||
return new CandleData(tick, open, close, high, low, averagePrice, accumulatedAmount, accumulatedVolume,
|
||||
isBullish, dateString);
|
||||
}
|
||||
|
||||
long getTickFromTime(long tradeDateAsTime, TickUnit tickUnit) {
|
||||
|
@ -267,4 +326,12 @@ class TradesChartsViewModel extends ActivatableViewModel {
|
|||
long tick = now - (maxTicks - index);
|
||||
return getTimeFromTick(tick, tickUnit);
|
||||
}
|
||||
|
||||
private boolean isShowAllEntry(String id) {
|
||||
return id.equals(GUIUtil.SHOW_ALL_FLAG);
|
||||
}
|
||||
|
||||
private boolean isEditEntry(String id) {
|
||||
return id.equals(GUIUtil.EDIT_FLAG);
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@
|
|||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.bitsquare.gui.main.markets.trades.charts;
|
||||
package io.bitsquare.gui.main.market.trades.charts;
|
||||
|
||||
public class CandleData {
|
||||
public final long tick; // Is the time tick in the chosen time interval
|
||||
|
@ -27,8 +27,9 @@ public class CandleData {
|
|||
public final long accumulatedAmount;
|
||||
public final long accumulatedVolume;
|
||||
public final boolean isBullish;
|
||||
public final String date;
|
||||
|
||||
public CandleData(long tick, long open, long close, long high, long low, long average, long accumulatedAmount, long accumulatedVolume, boolean isBullish) {
|
||||
public CandleData(long tick, long open, long close, long high, long low, long average, long accumulatedAmount, long accumulatedVolume, boolean isBullish, String date) {
|
||||
this.tick = tick;
|
||||
this.open = open;
|
||||
this.close = close;
|
||||
|
@ -38,5 +39,6 @@ public class CandleData {
|
|||
this.accumulatedAmount = accumulatedAmount;
|
||||
this.accumulatedVolume = accumulatedVolume;
|
||||
this.isBullish = isBullish;
|
||||
this.date = date;
|
||||
}
|
||||
}
|
|
@ -29,9 +29,9 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package io.bitsquare.gui.main.markets.trades.charts.price;
|
||||
package io.bitsquare.gui.main.market.trades.charts.price;
|
||||
|
||||
import io.bitsquare.gui.main.markets.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.Region;
|
||||
|
@ -48,7 +48,7 @@ public class Candle extends Group {
|
|||
|
||||
private String seriesStyleClass;
|
||||
private String dataStyleClass;
|
||||
private final TooltipContent tooltipContent;
|
||||
private final CandleTooltip candleTooltip;
|
||||
private final Line highLowLine = new Line();
|
||||
private final Region bar = new Region();
|
||||
|
||||
|
@ -65,8 +65,8 @@ public class Candle extends Group {
|
|||
getStyleClass().setAll("candlestick-candle", seriesStyleClass, dataStyleClass);
|
||||
updateStyleClasses();
|
||||
|
||||
tooltipContent = new TooltipContent(priceStringConverter);
|
||||
tooltip.setGraphic(tooltipContent);
|
||||
candleTooltip = new CandleTooltip(priceStringConverter);
|
||||
tooltip.setGraphic(candleTooltip);
|
||||
Tooltip.install(this, tooltip);
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class Candle extends Group {
|
|||
}
|
||||
|
||||
public void updateTooltip(CandleData candleData) {
|
||||
tooltipContent.update(candleData);
|
||||
candleTooltip.update(candleData);
|
||||
}
|
||||
|
||||
private void updateStyleClasses() {
|
|
@ -29,9 +29,9 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package io.bitsquare.gui.main.markets.trades.charts.price;
|
||||
package io.bitsquare.gui.main.market.trades.charts.price;
|
||||
|
||||
import io.bitsquare.gui.main.markets.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.Node;
|
||||
|
@ -70,16 +70,13 @@ public class CandleStickChart extends XYChart<Number, Number> {
|
|||
* @param xAxis The x axis to use
|
||||
* @param yAxis The y axis to use
|
||||
*/
|
||||
public CandleStickChart(Axis<Number> xAxis, Axis<Number> yAxis) {
|
||||
public CandleStickChart(Axis<Number> xAxis, Axis<Number> yAxis, StringConverter<Number> priceStringConverter) {
|
||||
super(xAxis, yAxis);
|
||||
this.priceStringConverter = priceStringConverter;
|
||||
}
|
||||
|
||||
// -------------- METHODS ------------------------------------------------------------------------------------------
|
||||
|
||||
public final void setToolTipStringConverter(StringConverter<Number> priceStringConverter) {
|
||||
this.priceStringConverter = priceStringConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update and layout the content for the plot
|
||||
*/
|
|
@ -29,29 +29,34 @@
|
|||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package io.bitsquare.gui.main.markets.trades.charts.price;
|
||||
package io.bitsquare.gui.main.market.trades.charts.price;
|
||||
|
||||
import io.bitsquare.gui.main.markets.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.ColumnConstraints;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
/**
|
||||
* The content for Candle tool tips
|
||||
*/
|
||||
public class TooltipContent extends GridPane {
|
||||
public class CandleTooltip extends GridPane {
|
||||
private final StringConverter<Number> priceStringConverter;
|
||||
private final Label openValue = new Label();
|
||||
private final Label closeValue = new Label();
|
||||
private final Label highValue = new Label();
|
||||
private final Label lowValue = new Label();
|
||||
private final Label averageValue = new Label();
|
||||
private final Label dateValue = new Label();
|
||||
|
||||
TooltipContent(StringConverter<Number> priceStringConverter) {
|
||||
CandleTooltip(StringConverter<Number> priceStringConverter) {
|
||||
this.priceStringConverter = priceStringConverter;
|
||||
|
||||
setHgap(Layout.GRID_GAP);
|
||||
|
||||
setVgap(2);
|
||||
|
||||
Label open = new Label("Open:");
|
||||
|
@ -59,10 +64,7 @@ public class TooltipContent extends GridPane {
|
|||
Label high = new Label("High:");
|
||||
Label low = new Label("Low:");
|
||||
Label average = new Label("Average:");
|
||||
/* open.getStyleClass().add("candlestick-tooltip-label");
|
||||
close.getStyleClass().add("candlestick-tooltip-label");
|
||||
high.getStyleClass().add("candlestick-tooltip-label");
|
||||
low.getStyleClass().add("candlestick-tooltip-label");*/
|
||||
Label date = new Label("Date:");
|
||||
setConstraints(open, 0, 0);
|
||||
setConstraints(openValue, 1, 0);
|
||||
setConstraints(close, 0, 1);
|
||||
|
@ -73,7 +75,17 @@ public class TooltipContent extends GridPane {
|
|||
setConstraints(lowValue, 1, 3);
|
||||
setConstraints(average, 0, 4);
|
||||
setConstraints(averageValue, 1, 4);
|
||||
getChildren().addAll(open, openValue, close, closeValue, high, highValue, low, lowValue, average, averageValue);
|
||||
setConstraints(date, 0, 5);
|
||||
setConstraints(dateValue, 1, 5);
|
||||
|
||||
ColumnConstraints columnConstraints1 = new ColumnConstraints();
|
||||
columnConstraints1.setHalignment(HPos.RIGHT);
|
||||
columnConstraints1.setHgrow(Priority.NEVER);
|
||||
ColumnConstraints columnConstraints2 = new ColumnConstraints();
|
||||
columnConstraints2.setHgrow(Priority.ALWAYS);
|
||||
getColumnConstraints().addAll(columnConstraints1, columnConstraints2);
|
||||
|
||||
getChildren().addAll(open, openValue, close, closeValue, high, highValue, low, lowValue, average, averageValue, date, dateValue);
|
||||
}
|
||||
|
||||
public void update(CandleData candleData) {
|
||||
|
@ -82,5 +94,6 @@ public class TooltipContent extends GridPane {
|
|||
highValue.setText(priceStringConverter.toString(candleData.high));
|
||||
lowValue.setText(priceStringConverter.toString(candleData.low));
|
||||
averageValue.setText(priceStringConverter.toString(candleData.average));
|
||||
dateValue.setText(candleData.date);
|
||||
}
|
||||
}
|
|
@ -14,8 +14,9 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.bitsquare.gui.main.markets.trades.charts.volume;
|
||||
package io.bitsquare.gui.main.market.trades.charts.volume;
|
||||
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.Region;
|
||||
|
@ -51,9 +52,10 @@ public class VolumeBar extends Group {
|
|||
updateStyleClasses();
|
||||
}
|
||||
|
||||
public void update(double height, double candleWidth, double accumulatedAmount) {
|
||||
public void update(double height, double candleWidth, CandleData candleData) {
|
||||
bar.resizeRelocate(-candleWidth / 2, 0, candleWidth, height);
|
||||
tooltip.setText("Volume: " + volumeStringConverter.toString(accumulatedAmount));
|
||||
tooltip.setText("Volume: " + volumeStringConverter.toString(candleData.accumulatedAmount) + "\n" +
|
||||
"Date: " + candleData.date);
|
||||
}
|
||||
|
||||
private void updateStyleClasses() {
|
|
@ -14,10 +14,10 @@
|
|||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package io.bitsquare.gui.main.markets.trades.charts.volume;
|
||||
package io.bitsquare.gui.main.market.trades.charts.volume;
|
||||
|
||||
import io.bitsquare.gui.main.markets.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.markets.trades.charts.price.CandleStickChart;
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.market.trades.charts.price.CandleStickChart;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.scene.Node;
|
||||
|
@ -38,11 +38,8 @@ public class VolumeChart extends XYChart<Number, Number> {
|
|||
|
||||
private StringConverter<Number> toolTipStringConverter;
|
||||
|
||||
public VolumeChart(Axis<Number> xAxis, Axis<Number> yAxis) {
|
||||
public VolumeChart(Axis<Number> xAxis, Axis<Number> yAxis, StringConverter<Number> toolTipStringConverter) {
|
||||
super(xAxis, yAxis);
|
||||
}
|
||||
|
||||
public final void setToolTipStringConverter(StringConverter<Number> toolTipStringConverter) {
|
||||
this.toolTipStringConverter = toolTipStringConverter;
|
||||
}
|
||||
|
||||
|
@ -73,7 +70,7 @@ public class VolumeChart extends XYChart<Number, Number> {
|
|||
// Did not find a way how to request the chart data height
|
||||
final double height = getHeight() - 43;
|
||||
double upperYPos = Math.min(height - 5, y); // We want min 5px height to allow tooltips
|
||||
volumeBar.update(height - upperYPos, candleWidth, candleData.accumulatedAmount);
|
||||
volumeBar.update(height - upperYPos, candleWidth, candleData);
|
||||
volumeBar.setLayoutX(x);
|
||||
volumeBar.setLayoutY(upperYPos);
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.markets.charts.MarketsChartsView"
|
||||
<VBox fx:id="root" fx:controller="io.bitsquare.gui.main.markets.offerbook.OfferBookChartView"
|
||||
spacing="20.0" fillWidth="true"
|
||||
AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
|
||||
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"
|
|
@ -333,7 +333,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
|||
"When another trader wants to take your offer it requires that your application is online and able to react.\n" +
|
||||
"Be sure that you have standby mode deactivated as that would disconnect your client from the network (standby of the monitor is not a problem).")
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> Utilities.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.onAction(() -> GUIUtil.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.closeButtonText("I understand")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
|
|
@ -22,7 +22,6 @@ import io.bitsquare.btc.pricefeed.MarketPrice;
|
|||
import io.bitsquare.btc.pricefeed.PriceFeedService;
|
||||
import io.bitsquare.common.Timer;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
||||
import io.bitsquare.gui.common.model.ViewModel;
|
||||
|
@ -33,6 +32,7 @@ import io.bitsquare.gui.main.overlays.popups.Popup;
|
|||
import io.bitsquare.gui.main.settings.SettingsView;
|
||||
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.validation.BtcValidator;
|
||||
import io.bitsquare.gui.util.validation.FiatValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
|
@ -355,7 +355,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
|
|||
"Be sure you fully understand the situation and check out the information on the \"Ethereum Classic\" and \"Ethereum\" project web pages.\n\n" +
|
||||
"Please note, that the price is denominated as ETC/BTC not BTC/ETC!")
|
||||
.closeButtonText("I understand")
|
||||
.onAction(() -> Utilities.openWebPage("https://ethereumclassic.github.io/"))
|
||||
.onAction(() -> GUIUtil.openWebPage("https://ethereumclassic.github.io/"))
|
||||
.actionButtonText("Open Ethereum Classic web page")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
|
|
@ -35,9 +35,9 @@ import io.bitsquare.gui.main.offer.OfferView;
|
|||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.Layout;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.locale.CryptoCurrency;
|
||||
import io.bitsquare.locale.FiatCurrency;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.payment.PaymentMethod;
|
||||
|
@ -107,28 +107,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||
|
||||
currencyComboBox = addLabelComboBox(root, gridRow, "Filter by currency:", Layout.FIRST_ROW_DISTANCE).second;
|
||||
currencyComboBox.setPromptText("Select currency");
|
||||
currencyComboBox.setConverter(new StringConverter<TradeCurrency>() {
|
||||
@Override
|
||||
public String toString(TradeCurrency tradeCurrency) {
|
||||
String code = tradeCurrency.getCode();
|
||||
// http://boschista.deviantart.com/journal/Cool-ASCII-Symbols-214218618
|
||||
if (code.equals(OfferBookViewModel.SHOW_ALL_FLAG))
|
||||
return "▶ Show all";
|
||||
else if (code.equals(OfferBookViewModel.EDIT_FLAG))
|
||||
return "▼ Edit currency list";
|
||||
else if (tradeCurrency instanceof FiatCurrency)
|
||||
return "★ " + tradeCurrency.getNameAndCode();
|
||||
else if (tradeCurrency instanceof CryptoCurrency)
|
||||
return "✦ " + tradeCurrency.getNameAndCode();
|
||||
else
|
||||
return "-";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeCurrency fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
currencyComboBox.setConverter(GUIUtil.getCurrencyListConverter());
|
||||
|
||||
paymentMethodComboBox = addLabelComboBox(root, ++gridRow, "Filter by payment method:").second;
|
||||
paymentMethodComboBox.setPromptText("Select payment method");
|
||||
|
@ -136,7 +115,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||
@Override
|
||||
public String toString(PaymentMethod paymentMethod) {
|
||||
String id = paymentMethod.getId();
|
||||
if (id.equals(OfferBookViewModel.SHOW_ALL_FLAG))
|
||||
if (id.equals(GUIUtil.SHOW_ALL_FLAG))
|
||||
return "▶ Show all";
|
||||
else if (paymentMethod.equals(PaymentMethod.BLOCK_CHAINS))
|
||||
return "✦ " + BSResources.get(id);
|
||||
|
|
|
@ -30,6 +30,7 @@ import io.bitsquare.gui.main.MainView;
|
|||
import io.bitsquare.gui.main.settings.SettingsView;
|
||||
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.locale.*;
|
||||
import io.bitsquare.p2p.NodeAddress;
|
||||
import io.bitsquare.p2p.P2PService;
|
||||
|
@ -60,9 +61,6 @@ import java.util.stream.Collectors;
|
|||
class OfferBookViewModel extends ActivatableViewModel {
|
||||
protected final static Logger log = LoggerFactory.getLogger(OfferBookViewModel.class);
|
||||
|
||||
final static String SHOW_ALL_FLAG = "SHOW_ALL_FLAG";
|
||||
final static String EDIT_FLAG = "EDIT_FLAG";
|
||||
|
||||
private final OpenOfferManager openOfferManager;
|
||||
private final User user;
|
||||
private final OfferBook offerBook;
|
||||
|
@ -87,8 +85,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
|||
|
||||
// If id is empty string we ignore filter (display all methods)
|
||||
|
||||
PaymentMethod selectedPaymentMethod = new PaymentMethod(SHOW_ALL_FLAG, 0, 0, null);
|
||||
private CryptoCurrency showAllCurrenciesItem = new CryptoCurrency(SHOW_ALL_FLAG, SHOW_ALL_FLAG);
|
||||
PaymentMethod selectedPaymentMethod = new PaymentMethod(GUIUtil.SHOW_ALL_FLAG, 0, 0, null);
|
||||
|
||||
private final ObservableList<OfferBookListItem> offerBookListItems;
|
||||
private boolean isTabSelected;
|
||||
|
@ -146,9 +143,9 @@ class OfferBookViewModel extends ActivatableViewModel {
|
|||
private void fillAllTradeCurrencies() {
|
||||
allTradeCurrencies.clear();
|
||||
// Used for ignoring filter (show all)
|
||||
allTradeCurrencies.add(showAllCurrenciesItem);
|
||||
allTradeCurrencies.add(new CryptoCurrency(GUIUtil.SHOW_ALL_FLAG, GUIUtil.SHOW_ALL_FLAG));
|
||||
allTradeCurrencies.addAll(preferences.getTradeCurrenciesAsObservable());
|
||||
allTradeCurrencies.add(new CryptoCurrency(EDIT_FLAG, EDIT_FLAG));
|
||||
allTradeCurrencies.add(new CryptoCurrency(GUIUtil.EDIT_FLAG, GUIUtil.EDIT_FLAG));
|
||||
}
|
||||
|
||||
private void setMarketPriceFeedCurrency() {
|
||||
|
@ -254,7 +251,7 @@ class OfferBookViewModel extends ActivatableViewModel {
|
|||
|
||||
public ObservableList<PaymentMethod> getPaymentMethods() {
|
||||
ObservableList<PaymentMethod> list = FXCollections.observableArrayList(PaymentMethod.ALL_VALUES);
|
||||
list.add(0, new PaymentMethod(SHOW_ALL_FLAG, 0, 0, null));
|
||||
list.add(0, new PaymentMethod(GUIUtil.SHOW_ALL_FLAG, 0, 0, null));
|
||||
return list;
|
||||
}
|
||||
|
||||
|
@ -418,11 +415,11 @@ class OfferBookViewModel extends ActivatableViewModel {
|
|||
}
|
||||
|
||||
private boolean isShowAllEntry(String id) {
|
||||
return id.equals(SHOW_ALL_FLAG);
|
||||
return id.equals(GUIUtil.SHOW_ALL_FLAG);
|
||||
}
|
||||
|
||||
private boolean isEditEntry(String id) {
|
||||
return id.equals(EDIT_FLAG);
|
||||
return id.equals(GUIUtil.EDIT_FLAG);
|
||||
}
|
||||
|
||||
int getNumPastTrades(Offer offer) {
|
||||
|
|
|
@ -334,7 +334,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
|||
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
||||
"It will be refunded to you after the trade has successfully completed.")
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> Utilities.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.onAction(() -> GUIUtil.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.closeButtonText("I understand")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
|
|
@ -19,7 +19,6 @@ package io.bitsquare.gui.main.offer.takeoffer;
|
|||
|
||||
import io.bitsquare.arbitration.Arbitrator;
|
||||
import io.bitsquare.btc.pricefeed.PriceFeedService;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.Navigation;
|
||||
import io.bitsquare.gui.common.model.ActivatableWithDataModel;
|
||||
import io.bitsquare.gui.common.model.ViewModel;
|
||||
|
@ -28,6 +27,7 @@ import io.bitsquare.gui.main.funds.FundsView;
|
|||
import io.bitsquare.gui.main.funds.deposit.DepositView;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.validation.BtcValidator;
|
||||
import io.bitsquare.gui.util.validation.InputValidator;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
|
@ -148,7 +148,7 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
|
|||
"Be sure you fully understand the situation and check out the information on the \"Ethereum Classic\" and \"Ethereum\" project web pages.\n\n" +
|
||||
"Please note, that the price is denominated as ETC/BTC not BTC/ETC!")
|
||||
.closeButtonText("I understand")
|
||||
.onAction(() -> Utilities.openWebPage("https://ethereumclassic.github.io/"))
|
||||
.onAction(() -> GUIUtil.openWebPage("https://ethereumclassic.github.io/"))
|
||||
.actionButtonText("Open Ethereum Classic web page")
|
||||
.dontShowAgainId(key, dataModel.getPreferences())
|
||||
.show();
|
||||
|
|
|
@ -22,6 +22,7 @@ import io.bitsquare.common.UserThread;
|
|||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.components.BusyAnimation;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.gui.util.Transitions;
|
||||
import io.bitsquare.locale.BSResources;
|
||||
import io.bitsquare.user.Preferences;
|
||||
|
@ -680,7 +681,7 @@ public abstract class Overlay<T extends Overlay> {
|
|||
|
||||
githubButton.setOnAction(event -> {
|
||||
Utilities.copyToClipboard(message);
|
||||
Utilities.openWebPage("https://github.com/bitsquare/bitsquare/issues");
|
||||
GUIUtil.openWebPage("https://github.com/bitsquare/bitsquare/issues");
|
||||
});
|
||||
|
||||
Button mailButton = new Button("Report by email");
|
||||
|
@ -690,7 +691,7 @@ public abstract class Overlay<T extends Overlay> {
|
|||
gridPane.getChildren().add(mailButton);
|
||||
mailButton.setOnAction(event -> {
|
||||
Utilities.copyToClipboard(message);
|
||||
Utilities.openMail("manfred@bitsquare.io",
|
||||
GUIUtil.openMail("manfred@bitsquare.io",
|
||||
"Error report",
|
||||
"Error message:\n" + message);
|
||||
});
|
||||
|
|
|
@ -19,8 +19,8 @@ package io.bitsquare.gui.main.overlays.windows;
|
|||
|
||||
import io.bitsquare.alert.Alert;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.main.overlays.Overlay;
|
||||
import io.bitsquare.gui.util.GUIUtil;
|
||||
import io.bitsquare.user.Preferences;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
|
@ -90,7 +90,7 @@ public class AddBridgeEntriesWindow extends Overlay<AddBridgeEntriesWindow> {
|
|||
actionButton.setOnAction(event -> save());
|
||||
|
||||
Button urlButton = new Button("Open Tor project web page");
|
||||
urlButton.setOnAction(event -> Utilities.openWebPage("https://bridges.torproject.org/bridges"));
|
||||
urlButton.setOnAction(event -> GUIUtil.openWebPage("https://bridges.torproject.org/bridges"));
|
||||
|
||||
Pane spacer = new Pane();
|
||||
HBox hBox = new HBox();
|
||||
|
|
|
@ -199,18 +199,23 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
|||
final PaymentMethod paymentMethod = offer.getPaymentMethod();
|
||||
final String offererPaymentAccountId = offer.getOffererPaymentAccountId();
|
||||
final PaymentAccount paymentAccount = user.getPaymentAccount(offererPaymentAccountId);
|
||||
final String bankId = offer.getBankId();
|
||||
String bankId = offer.getBankId();
|
||||
if (bankId == null || bankId.equals("null"))
|
||||
bankId = "";
|
||||
else
|
||||
bankId = " (" + bankId + ")";
|
||||
final boolean isSpecificBanks = paymentMethod.equals(PaymentMethod.SPECIFIC_BANKS);
|
||||
final boolean isNationalBanks = paymentMethod.equals(PaymentMethod.NATIONAL_BANK);
|
||||
final boolean isSepa = paymentMethod.equals(PaymentMethod.SEPA);
|
||||
if (offer.isMyOffer(keyRing) && offererPaymentAccountId != null && paymentAccount != null) {
|
||||
addLabelTextField(gridPane, ++rowIndex, "Payment account:", paymentAccount.getAccountName());
|
||||
} else {
|
||||
final String method = BSResources.get(paymentMethod.getId());
|
||||
if (isNationalBanks || isSpecificBanks) {
|
||||
if (isNationalBanks || isSpecificBanks || isSepa) {
|
||||
if (BankUtil.isBankIdRequired(offer.getCountryCode()))
|
||||
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerers bank ID):", method + " (" + bankId + ")");
|
||||
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerers bank ID):", method + bankId);
|
||||
else if (BankUtil.isBankNameRequired(offer.getCountryCode()))
|
||||
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerers bank name):", method + " (" + bankId + ")");
|
||||
addLabelTextField(gridPane, ++rowIndex, "Payment method (offerers bank name):", method + bankId);
|
||||
} else {
|
||||
addLabelTextField(gridPane, ++rowIndex, "Payment method:", method);
|
||||
}
|
||||
|
|
|
@ -372,7 +372,6 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
|
|||
}
|
||||
|
||||
private void doRestore() {
|
||||
log.info("Attempting wallet restore using seed '{}' from date {}", restoreSeedWordsTextArea.getText(), restoreDatePicker.getValue());
|
||||
long date = restoreDatePicker.getValue().atStartOfDay().toEpochSecond(ZoneOffset.UTC);
|
||||
DeterministicSeed seed = new DeterministicSeed(Splitter.on(" ").splitToList(restoreSeedWordsTextArea.getText()), null, "", date);
|
||||
walletService.restoreSeedWords(seed,
|
||||
|
|
|
@ -92,14 +92,15 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
|
|||
dateColumn.setComparator((o1, o2) -> o1.getTradable().getDate().compareTo(o2.getTradable().getDate()));
|
||||
directionColumn.setComparator((o1, o2) -> o1.getTradable().getOffer().getDirection().compareTo(o2.getTradable().getOffer().getDirection()));
|
||||
priceColumn.setComparator((o1, o2) -> {
|
||||
Tradable tradable = o1.getTradable();
|
||||
if (tradable instanceof Trade)
|
||||
return ((Trade) o1.getTradable()).getTradePrice().compareTo(((Trade) o2.getTradable()).getTradePrice());
|
||||
else {
|
||||
Fiat price1 = o1.getTradable().getOffer().getPrice();
|
||||
Fiat price2 = o2.getTradable().getOffer().getPrice();
|
||||
return price1 != null && price2 != null ? price1.compareTo(price2) : 0;
|
||||
}
|
||||
final Tradable tradable1 = o1.getTradable();
|
||||
final Tradable tradable2 = o2.getTradable();
|
||||
Fiat price1 = null;
|
||||
Fiat price2 = null;
|
||||
if (tradable1 != null)
|
||||
price1 = tradable1 instanceof Trade ? ((Trade) tradable1).getTradePrice() : tradable1.getOffer().getPrice();
|
||||
if (tradable2 != null)
|
||||
price2 = tradable2 instanceof Trade ? ((Trade) tradable2).getTradePrice() : tradable2.getOffer().getPrice();
|
||||
return price1 != null && price2 != null ? price1.compareTo(price2) : 0;
|
||||
});
|
||||
volumeColumn.setComparator((o1, o2) -> {
|
||||
if (o1.getTradable() instanceof Trade && o2.getTradable() instanceof Trade) {
|
||||
|
|
|
@ -304,7 +304,7 @@ public class PendingTradesDataModel extends ActivatableDataModel {
|
|||
if (depositTx != null) {
|
||||
doOpenDispute(isSupportTicket, getTrade().getDepositTx());
|
||||
} else {
|
||||
log.warn("Trade.depositTx is null. We try to find the tx in our wallet.");
|
||||
log.info("Trade.depositTx is null. We try to find the tx in our wallet.");
|
||||
List<Transaction> candidates = new ArrayList<>();
|
||||
List<Transaction> transactions = walletService.getWallet().getRecentTransactions(100, true);
|
||||
transactions.stream().forEach(transaction -> {
|
||||
|
|
|
@ -21,7 +21,6 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
|
|||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.common.util.Tuple4;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.components.*;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
|
@ -170,7 +169,7 @@ public class FormBuilder {
|
|||
|
||||
public static HyperlinkWithIcon addHyperlinkWithIcon(GridPane gridPane, int rowIndex, String title, String url, double top) {
|
||||
HyperlinkWithIcon hyperlinkWithIcon = new HyperlinkWithIcon(title, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(e -> Utilities.openWebPage(url));
|
||||
hyperlinkWithIcon.setOnAction(e -> GUIUtil.openWebPage(url));
|
||||
GridPane.setRowIndex(hyperlinkWithIcon, rowIndex);
|
||||
GridPane.setColumnIndex(hyperlinkWithIcon, 0);
|
||||
GridPane.setMargin(hyperlinkWithIcon, new Insets(top, 0, 0, -4));
|
||||
|
@ -191,7 +190,7 @@ public class FormBuilder {
|
|||
Label label = addLabel(gridPane, rowIndex, labelTitle, top);
|
||||
|
||||
HyperlinkWithIcon hyperlinkWithIcon = new HyperlinkWithIcon(title, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(e -> Utilities.openWebPage(url));
|
||||
hyperlinkWithIcon.setOnAction(e -> GUIUtil.openWebPage(url));
|
||||
GridPane.setRowIndex(hyperlinkWithIcon, rowIndex);
|
||||
GridPane.setColumnIndex(hyperlinkWithIcon, 1);
|
||||
GridPane.setMargin(hyperlinkWithIcon, new Insets(top, 0, 0, -4));
|
||||
|
|
|
@ -23,7 +23,11 @@ import com.googlecode.jcsv.writer.CSVEntryConverter;
|
|||
import com.googlecode.jcsv.writer.CSVWriter;
|
||||
import com.googlecode.jcsv.writer.internal.CSVWriterBuilder;
|
||||
import io.bitsquare.app.DevFlags;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.locale.CryptoCurrency;
|
||||
import io.bitsquare.locale.FiatCurrency;
|
||||
import io.bitsquare.locale.TradeCurrency;
|
||||
import io.bitsquare.payment.PaymentAccount;
|
||||
import io.bitsquare.storage.Storage;
|
||||
import io.bitsquare.user.Preferences;
|
||||
|
@ -34,6 +38,7 @@ import javafx.scene.control.ScrollBar;
|
|||
import javafx.stage.DirectoryChooser;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.StringConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -41,6 +46,9 @@ import java.io.File;
|
|||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -48,6 +56,9 @@ import java.util.List;
|
|||
public class GUIUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(GUIUtil.class);
|
||||
|
||||
public final static String SHOW_ALL_FLAG = "SHOW_ALL_FLAG";
|
||||
public final static String EDIT_FLAG = "EDIT_FLAG";
|
||||
|
||||
public static double getScrollbarWidth(Node scrollablePane) {
|
||||
Node node = scrollablePane.lookup(".scroll-bar");
|
||||
if (node instanceof ScrollBar) {
|
||||
|
@ -81,7 +92,7 @@ public class GUIUtil {
|
|||
String directory = getDirectoryFormChooser(preferences, stage);
|
||||
Storage<ArrayList<PaymentAccount>> paymentAccountsStorage = new Storage<>(new File(directory));
|
||||
paymentAccountsStorage.initAndGetPersisted(accounts, fileName);
|
||||
paymentAccountsStorage.queueUpForSave(20);
|
||||
paymentAccountsStorage.queueUpForSave();
|
||||
new Popup<>().feedback("Payment accounts saved to path:\n" + Paths.get(directory, fileName).toAbsolutePath()).show();
|
||||
} else {
|
||||
new Popup<>().warning("You don't have payment accounts set up for exporting.").show();
|
||||
|
@ -163,4 +174,73 @@ public class GUIUtil {
|
|||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static StringConverter<TradeCurrency> getCurrencyListConverter() {
|
||||
return new StringConverter<TradeCurrency>() {
|
||||
@Override
|
||||
public String toString(TradeCurrency tradeCurrency) {
|
||||
String code = tradeCurrency.getCode();
|
||||
// http://boschista.deviantart.com/journal/Cool-ASCII-Symbols-214218618
|
||||
if (code.equals(GUIUtil.SHOW_ALL_FLAG))
|
||||
return "▶ Show all";
|
||||
else if (code.equals(GUIUtil.EDIT_FLAG))
|
||||
return "▼ Edit currency list";
|
||||
else if (tradeCurrency instanceof FiatCurrency)
|
||||
return "★ " + tradeCurrency.getNameAndCode();
|
||||
else if (tradeCurrency instanceof CryptoCurrency)
|
||||
return "✦ " + tradeCurrency.getNameAndCode();
|
||||
else
|
||||
return "-";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TradeCurrency fromString(String s) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
public static void openWebPage(String target) {
|
||||
String key = "warnOpenURLWhenTorEnabled";
|
||||
final Preferences preferences = Preferences.INSTANCE;
|
||||
if (preferences.getUseTorForHttpRequests() && preferences.showAgain(key)) {
|
||||
new Popup<>().information("You have Tor enabled for Http requests and are going to open a web page " +
|
||||
"in your system web browser.\n" +
|
||||
"Do you want to open the web page now?\n\n" +
|
||||
"If you are not using the \"Tor Browser\" as your default system web browser you " +
|
||||
"will connect to the web page in clear net.\n\n" +
|
||||
"URL: \"" + target)
|
||||
.actionButtonText("Open the web page and don't ask again")
|
||||
.onAction(() -> {
|
||||
preferences.dontShowAgain(key, true);
|
||||
doOpenWebPage(target);
|
||||
})
|
||||
.closeButtonText("Copy URL and cancel")
|
||||
.onClose(() -> Utilities.copyToClipboard(target))
|
||||
.show();
|
||||
} else {
|
||||
doOpenWebPage(target);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doOpenWebPage(String target) {
|
||||
try {
|
||||
Utilities.openURI(new URI(target));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void openMail(String to, String subject, String body) {
|
||||
try {
|
||||
subject = URLEncoder.encode(subject, "UTF-8").replace("+", "%20");
|
||||
body = URLEncoder.encode(body, "UTF-8").replace("+", "%20");
|
||||
Utilities.openURI(new URI("mailto:" + to + "?subject=" + subject + "&body=" + body));
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
log.error("openMail failed " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,7 +57,7 @@ public class ImageUtil {
|
|||
public static boolean isRetina() {
|
||||
float maxRenderScale = ((QuantumToolkit) QuantumToolkit.getToolkit()).getMaxRenderScale();
|
||||
boolean isRetina = maxRenderScale > 1.9f;
|
||||
//log.info("isRetina=" + isRetina + " / maxRenderScale=" + maxRenderScale);
|
||||
//log.debug("isRetina=" + isRetina + " / maxRenderScale=" + maxRenderScale);
|
||||
return isRetina;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,21 +10,21 @@
|
|||
<appender-ref ref="CONSOLE_APPENDER"/>
|
||||
</root>
|
||||
|
||||
<logger name="io.bitsquare.storage.Storage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
||||
|
||||
<!--<logger name="io.bitsquare.p2p" level="WARN"/>-->
|
||||
<logger name="io.bitsquare.btc.pricefeed" level="WARN"/>
|
||||
|
||||
|
||||
<logger name="io.bitsquare.storage.Storage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
|
||||
<logger name="io.bitsquare.p2p.peers" level="WARN"/>
|
||||
<logger name="io.bitsquare.p2p.peers.getdata" level="WARN"/>
|
||||
<logger name="io.bitsquare.p2p.peers.keepalive" level="WARN"/>
|
||||
<logger name="io.bitsquare.p2p.peers.peerexchange" level="WARN"/>
|
||||
<!-- <logger name="io.bitsquare.storage.Storage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
|
||||
|
||||
<!–<logger name="io.bitsquare.p2p" level="WARN"/>–>
|
||||
<logger name="io.bitsquare.btc.pricefeed" level="WARN"/>
|
||||
|
||||
|
||||
<logger name="io.bitsquare.storage.Storage" level="WARN"/>
|
||||
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>
|
||||
|
||||
<logger name="io.bitsquare.p2p.peers" level="WARN"/>
|
||||
<logger name="io.bitsquare.p2p.peers.getdata" level="WARN"/>
|
||||
<logger name="io.bitsquare.p2p.peers.keepalive" level="WARN"/>
|
||||
<logger name="io.bitsquare.p2p.peers.peerexchange" level="WARN"/>-->
|
||||
|
||||
<!--<logger name="io.bitsquare.p2p.network" level="WARN"/>-->
|
||||
<!-- <logger name="io.bitsquare.p2p.P2PService" level="WARN"/>-->
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.bitsquare.gui.main.markets.trades;
|
||||
package io.bitsquare.gui.main.market.trades;
|
||||
|
||||
import io.bitsquare.gui.main.markets.trades.charts.CandleData;
|
||||
import io.bitsquare.gui.main.market.trades.charts.CandleData;
|
||||
import io.bitsquare.trade.offer.Offer;
|
||||
import io.bitsquare.trade.statistics.TradeStatistics;
|
||||
import org.bitcoinj.core.Coin;
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -127,7 +127,7 @@ public class Headless {
|
|||
|
||||
public void shutDown() {
|
||||
gracefulShutDown(() -> {
|
||||
log.info("Shutdown complete");
|
||||
log.debug("Shutdown complete");
|
||||
System.exit(0);
|
||||
});
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ public class Headless {
|
|||
injector.getInstance(P2PService.class).shutDown(() -> {
|
||||
injector.getInstance(WalletService.class).shutDownDone.addListener((ov, o, n) -> {
|
||||
headlessModule.close(injector);
|
||||
log.info("Graceful shutdown completed");
|
||||
log.debug("Graceful shutdown completed");
|
||||
resultHandler.handleResult();
|
||||
});
|
||||
injector.getInstance(WalletService.class).shutDown();
|
||||
|
@ -153,7 +153,7 @@ public class Headless {
|
|||
UserThread.runAfter(resultHandler::handleResult, 1);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.info("App shutdown failed with exception");
|
||||
log.debug("App shutdown failed with exception");
|
||||
t.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -257,7 +257,7 @@ public class SOCKS {
|
|||
// /////////////////
|
||||
|
||||
static void inform(String s) {
|
||||
log.info(s);
|
||||
log.debug(s);
|
||||
}
|
||||
|
||||
static void exit(String msg) {
|
||||
|
|
|
@ -158,13 +158,13 @@ public class ProxyServer implements Runnable {
|
|||
ss = new ServerSocket(port, backlog, localIP);
|
||||
final String address = ss.getInetAddress().getHostAddress();
|
||||
final int localPort = ss.getLocalPort();
|
||||
log.info("Starting SOCKS Proxy on: {}:{}", address, localPort);
|
||||
log.debug("Starting SOCKS Proxy on: {}:{}", address, localPort);
|
||||
|
||||
while (true) {
|
||||
final Socket s = ss.accept();
|
||||
final String hostName = s.getInetAddress().getHostName();
|
||||
final int port2 = s.getPort();
|
||||
log.info("Accepted from:{}:{}", hostName, port2);
|
||||
log.debug("Accepted from:{}:{}", hostName, port2);
|
||||
|
||||
final ProxyServer ps = new ProxyServer(auth, s);
|
||||
(new Thread(ps)).start();
|
||||
|
@ -203,7 +203,7 @@ public class ProxyServer implements Runnable {
|
|||
if (auth != null) {
|
||||
auth.endSession();
|
||||
}
|
||||
log.info("Main thread(client->remote)stopped.");
|
||||
log.debug("Main thread(client->remote)stopped.");
|
||||
}
|
||||
break;
|
||||
case ACCEPT_MODE:
|
||||
|
@ -219,7 +219,7 @@ public class ProxyServer implements Runnable {
|
|||
handleException(ioe);
|
||||
} finally {
|
||||
abort();
|
||||
log.info("Accept thread(remote->client) stopped");
|
||||
log.debug("Accept thread(remote->client) stopped");
|
||||
}
|
||||
break;
|
||||
case PIPE_MODE:
|
||||
|
@ -228,7 +228,7 @@ public class ProxyServer implements Runnable {
|
|||
} catch (final IOException ioe) {
|
||||
} finally {
|
||||
abort();
|
||||
log.info("Support thread(remote->client) stopped");
|
||||
log.debug("Support thread(remote->client) stopped");
|
||||
}
|
||||
break;
|
||||
case ABORT_MODE:
|
||||
|
@ -252,7 +252,7 @@ public class ProxyServer implements Runnable {
|
|||
}
|
||||
|
||||
if (auth == null) { // Authentication failed
|
||||
log.info("Authentication failed");
|
||||
log.debug("Authentication failed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ public class ProxyServer implements Runnable {
|
|||
s = new SocksSocket(proxy, msg.ip, msg.port);
|
||||
}
|
||||
|
||||
log.info("Connected to " + s.getInetAddress() + ":" + s.getPort());
|
||||
log.debug("Connected to " + s.getInetAddress() + ":" + s.getPort());
|
||||
|
||||
ProxyMessage response = null;
|
||||
final InetAddress localAddress = s.getLocalAddress();
|
||||
|
@ -367,7 +367,7 @@ public class ProxyServer implements Runnable {
|
|||
|
||||
final InetAddress inetAddress = ss.getInetAddress();
|
||||
final int localPort = ss.getLocalPort();
|
||||
log.info("Trying accept on {}:{}", inetAddress, localPort);
|
||||
log.debug("Trying accept on {}:{}", inetAddress, localPort);
|
||||
|
||||
if (msg.version == 5) {
|
||||
final int cmd = SocksProxyBase.SOCKS_SUCCESS;
|
||||
|
@ -425,7 +425,7 @@ public class ProxyServer implements Runnable {
|
|||
if (msg.ip.getHostAddress().equals("0.0.0.0")) {
|
||||
msg.ip = sock.getInetAddress();
|
||||
}
|
||||
log.info("Creating UDP relay server for {}:{}", msg.ip, msg.port);
|
||||
log.debug("Creating UDP relay server for {}:{}", msg.ip, msg.port);
|
||||
|
||||
relayServer = new UDPRelayServer(msg.ip, msg.port,
|
||||
Thread.currentThread(), sock, auth);
|
||||
|
@ -494,7 +494,7 @@ public class ProxyServer implements Runnable {
|
|||
|
||||
final InetAddress inetAddress = s.getInetAddress();
|
||||
final int port = s.getPort();
|
||||
log.info("Accepted from {}:{}", s.getInetAddress(), port);
|
||||
log.debug("Accepted from {}:{}", s.getInetAddress(), port);
|
||||
|
||||
ProxyMessage response;
|
||||
|
||||
|
@ -564,7 +564,7 @@ public class ProxyServer implements Runnable {
|
|||
}
|
||||
mode = ABORT_MODE;
|
||||
try {
|
||||
log.info("Aborting operation");
|
||||
log.debug("Aborting operation");
|
||||
if (remote_sock != null) {
|
||||
remote_sock.close();
|
||||
}
|
||||
|
|
|
@ -115,8 +115,8 @@ class UDPRelayServer implements Runnable {
|
|||
remote_sock.setSoTimeout(iddleTimeout);
|
||||
client_sock.setSoTimeout(iddleTimeout);
|
||||
|
||||
log.info("Starting UDP relay server on {}:{}", relayIP, relayPort);
|
||||
log.info("Remote socket {}:{}", remote_sock.getLocalAddress(),
|
||||
log.debug("Starting UDP relay server on {}:{}", relayIP, relayPort);
|
||||
log.debug("Remote socket {}:{}", remote_sock.getLocalAddress(),
|
||||
remote_sock.getLocalPort());
|
||||
|
||||
pipe_thread1 = new Thread(this, "pipe1");
|
||||
|
@ -151,7 +151,7 @@ class UDPRelayServer implements Runnable {
|
|||
} catch (final IOException ioe) {
|
||||
} finally {
|
||||
abort();
|
||||
log.info("UDP Pipe thread " + Thread.currentThread().getName()
|
||||
log.debug("UDP Pipe thread " + Thread.currentThread().getName()
|
||||
+ " stopped.");
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ class UDPRelayServer implements Runnable {
|
|||
return;
|
||||
}
|
||||
|
||||
log.info("Aborting UDP Relay Server");
|
||||
log.debug("Aborting UDP Relay Server");
|
||||
|
||||
remote_sock.close();
|
||||
client_sock.close();
|
||||
|
@ -201,7 +201,7 @@ class UDPRelayServer implements Runnable {
|
|||
}
|
||||
|
||||
} catch (final UnknownHostException uhe) {
|
||||
log.info("Dropping datagram for unknown host");
|
||||
log.debug("Dropping datagram for unknown host");
|
||||
} catch (final InterruptedIOException iioe) {
|
||||
// log("Interrupted: "+iioe);
|
||||
// If we were interrupted by other thread.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>parent</artifactId>
|
||||
<groupId>io.bitsquare</groupId>
|
||||
<version>0.4.9.1</version>
|
||||
<version>0.4.9.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue