Merge branch 'Development'

This commit is contained in:
Manfred Karrer 2016-07-30 01:58:28 +02:00
commit ef46e50798
136 changed files with 1089 additions and 758 deletions

View file

@ -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>

View file

@ -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.

View file

@ -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();

View file

@ -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() {

View file

@ -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;

View file

@ -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.");
}

View 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>

View file

@ -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";

View file

@ -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();
}

View file

@ -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() {

View file

@ -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() {

View file

@ -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 {

View file

@ -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);

View file

@ -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());

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -58,6 +58,7 @@ class GetPriceRequest {
}
public void onFailure(@NotNull Throwable throwable) {
log.error("requestPrice.onFailure: throwable=" + throwable.toString());
resultFuture.setException(throwable);
}
});

View file

@ -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);
}

View file

@ -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);

View 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;
}
}

View file

@ -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() {

View file

@ -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() {

View file

@ -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();

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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));
}
}

View file

@ -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);
}

View file

@ -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");

View file

@ -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();
}

View file

@ -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");

View file

@ -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");

View file

@ -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");

View file

@ -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.");

View file

@ -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);
}
}

View file

@ -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();
}
}

View file

@ -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() {

View file

@ -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

View 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>

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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));
}

View file

@ -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();
}

View file

@ -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

View file

@ -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 " +

View file

@ -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"));

View file

@ -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);

View file

@ -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();
}

View file

@ -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,

View file

@ -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 " +

View file

@ -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 " +

View file

@ -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 " +

View file

@ -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 " +

View file

@ -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 " +

View file

@ -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());

View file

@ -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">

View file

@ -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());

View file

@ -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>

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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"

View file

@ -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)

View file

@ -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));
}
}
}

View file

@ -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"

View file

@ -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("");
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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() {

View file

@ -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
*/

View file

@ -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);
}
}

View file

@ -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() {

View file

@ -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);
}

View file

@ -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"

View file

@ -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();

View file

@ -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();

View file

@ -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);

View file

@ -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) {

View file

@ -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();

View file

@ -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();

View file

@ -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);
});

View file

@ -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();

View file

@ -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);
}

View file

@ -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,

View file

@ -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) {

View file

@ -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 -> {

View file

@ -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));

View file

@ -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();
}
}
}

View file

@ -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;
}
}

View file

@ -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"/>
&lt;!&ndash;<logger name="io.bitsquare.p2p" level="WARN"/>&ndash;&gt;
<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"/>-->

View file

@ -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;

View file

@ -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>

View file

@ -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);
}

View 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>

View file

@ -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>

View file

@ -257,7 +257,7 @@ public class SOCKS {
// /////////////////
static void inform(String s) {
log.info(s);
log.debug(s);
}
static void exit(String msg) {

View file

@ -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();
}

View file

@ -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.

View file

@ -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>

View file

@ -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