Add market price feed

This commit is contained in:
Manfred Karrer 2016-02-10 01:59:46 +01:00
parent 30f7ca69f8
commit d2e8c6afd7
37 changed files with 676 additions and 102 deletions

View file

@ -76,7 +76,7 @@ import static io.bitsquare.app.BitsquareEnvironment.APP_NAME_KEY;
public class BitsquareApp extends Application {
private static final Logger log = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(BitsquareApp.class);
public static final boolean DEV_MODE = false;
public static final boolean DEV_MODE = true;
public static final boolean IS_RELEASE_VERSION = !DEV_MODE && true;
private static Environment env;
@ -153,7 +153,7 @@ public class BitsquareApp extends Application {
mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles);
});*/
scene = new Scene(mainView.getRoot(), 1000, 740);
scene = new Scene(mainView.getRoot(), 1100, 740);
scene.getStylesheets().setAll(
"/io/bitsquare/gui/bitsquare.css",
"/io/bitsquare/gui/images.css");

View file

@ -19,8 +19,10 @@ package io.bitsquare.gui.main;
import io.bitsquare.BitsquareException;
import io.bitsquare.app.BitsquareApp;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.common.util.Tuple3;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.*;
import io.bitsquare.gui.main.account.AccountView;
@ -47,6 +49,7 @@ import javax.inject.Inject;
import javax.inject.Named;
import java.util.List;
import static javafx.beans.binding.Bindings.createStringBinding;
import static javafx.scene.layout.AnchorPane.*;
@FxmlView
@ -121,6 +124,22 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
setTopAnchor(this, 0d);
}};
Tuple3<TextField, Label, VBox> marketPriceBox = getMarketPriceBox("Market price");
marketPriceBox.first.textProperty().bind(createStringBinding(
() -> {
return model.marketPrice.get() + " " +
model.marketPriceCurrency.get() + "/BTC";
},
model.marketPriceCurrency, model.marketPrice));
marketPriceBox.second.textProperty().bind(createStringBinding(
() -> {
MarketPriceFeed.Type type = model.typeProperty.get();
return type != null ? "Market price (" + type.name + ")" : "";
},
model.marketPriceCurrency, model.typeProperty));
HBox.setMargin(marketPriceBox.third, new Insets(0, 20, 0, 0));
Tuple2<TextField, VBox> availableBalanceBox = getBalanceBox("Available balance");
availableBalanceBox.first.textProperty().bind(model.availableBalance);
@ -130,7 +149,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
Tuple2<TextField, VBox> lockedBalanceBox = getBalanceBox("Locked balance");
lockedBalanceBox.first.textProperty().bind(model.lockedBalance);
HBox rightNavPane = new HBox(availableBalanceBox.second, reservedBalanceBox.second, lockedBalanceBox.second,
HBox rightNavPane = new HBox(marketPriceBox.third, availableBalanceBox.second, reservedBalanceBox.second, lockedBalanceBox.second,
settingsButton, accountButton) {{
setSpacing(10);
setRightAnchor(this, 10d);
@ -225,6 +244,25 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
return new Tuple2(textField, vBox);
}
private Tuple3<TextField, Label, VBox> getMarketPriceBox(String text) {
TextField textField = new TextField();
textField.setEditable(false);
textField.setPrefWidth(140);
textField.setMouseTransparent(true);
textField.setFocusTraversable(false);
textField.setStyle("-fx-alignment: center; -fx-background-color: -bs-bg-grey;");
Label label = new Label(text);
label.setId("nav-balance-label");
label.setPadding(new Insets(0, 5, 0, 5));
label.setPrefWidth(textField.getPrefWidth());
VBox vBox = new VBox();
vBox.setSpacing(3);
vBox.setPadding(new Insets(11, 0, 0, 0));
vBox.getChildren().addAll(textField, label);
return new Tuple3(textField, label, vBox);
}
public void setPersistedFilesCorrupted(List<String> persistedFilesCorrupted) {
this.persistedFilesCorrupted = persistedFilesCorrupted;
}

View file

@ -28,6 +28,7 @@ import io.bitsquare.arbitration.Dispute;
import io.bitsquare.arbitration.DisputeManager;
import io.bitsquare.btc.*;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.common.UserThread;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.model.ViewModel;
@ -99,6 +100,9 @@ public class MainViewModel implements ViewModel {
final DoubleProperty btcSyncProgress = new SimpleDoubleProperty(-1);
final StringProperty walletServiceErrorMsg = new SimpleStringProperty();
final StringProperty btcSplashSyncIconId = new SimpleStringProperty();
final StringProperty marketPrice = new SimpleStringProperty("N/A");
final StringProperty marketPriceCurrency = new SimpleStringProperty("");
final ObjectProperty<MarketPriceFeed.Type> typeProperty = new SimpleObjectProperty<>(MarketPriceFeed.Type.LAST);
final StringProperty availableBalance = new SimpleStringProperty();
final StringProperty reservedBalance = new SimpleStringProperty();
final StringProperty lockedBalance = new SimpleStringProperty();
@ -123,6 +127,7 @@ public class MainViewModel implements ViewModel {
final StringProperty p2PNetworkLabelId = new SimpleStringProperty("footer-pane");
private MonadicBinding<Boolean> allServicesDone, tradesAndUIReady;
private MarketPriceFeed marketPriceFeed;
private final User user;
private int numBTCPeers = 0;
private Timer checkForBtcSyncStateTimer;
@ -138,10 +143,12 @@ public class MainViewModel implements ViewModel {
@Inject
public MainViewModel(WalletService walletService, TradeWalletService tradeWalletService,
MarketPriceFeed marketPriceFeed,
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
User user, AlertManager alertManager, WalletPasswordPopup walletPasswordPopup,
Navigation navigation, BSFormatter formatter) {
this.marketPriceFeed = marketPriceFeed;
this.user = user;
this.walletService = walletService;
this.tradeWalletService = tradeWalletService;
@ -497,6 +504,19 @@ public class MainViewModel implements ViewModel {
okPayAccount.setCountry(CountryUtil.getDefaultCountry());
user.addPaymentAccount(okPayAccount);
}
if (marketPriceFeed.getCurrencyCode() == null)
marketPriceFeed.setCurrencyCode(preferences.getPreferredTradeCurrency().getCode());
if (marketPriceFeed.getType() == null)
marketPriceFeed.setType(MarketPriceFeed.Type.LAST);
marketPriceFeed.init(price -> {
marketPrice.set(formatter.formatMarketPrice(price));
},
(errorMessage, throwable) -> {
marketPrice.set("N/A");
});
marketPriceCurrency.bind(marketPriceFeed.currencyCodeProperty());
typeProperty.bind(marketPriceFeed.typeProperty());
}
private void checkPeriodicallyForBtcSyncState() {

View file

@ -19,6 +19,7 @@ package io.bitsquare.gui.main.markets.charts;
import com.google.common.math.LongMath;
import com.google.inject.Inject;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.gui.common.model.ActivatableViewModel;
import io.bitsquare.gui.main.offer.offerbook.OfferBook;
import io.bitsquare.gui.main.offer.offerbook.OfferBookListItem;
@ -41,6 +42,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
private final OfferBook offerBook;
private final Preferences preferences;
private MarketPriceFeed marketPriceFeed;
final ObjectProperty<TradeCurrency> tradeCurrency = new SimpleObjectProperty<>(CurrencyUtil.getDefaultTradeCurrency());
private final List<XYChart.Data> buyData = new ArrayList();
@ -56,9 +58,10 @@ class MarketsChartsViewModel extends ActivatableViewModel {
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
public MarketsChartsViewModel(OfferBook offerBook, Preferences preferences) {
public MarketsChartsViewModel(OfferBook offerBook, Preferences preferences, MarketPriceFeed marketPriceFeed) {
this.offerBook = offerBook;
this.preferences = preferences;
this.marketPriceFeed = marketPriceFeed;
offerBookListItems = offerBook.getOfferBookListItems();
listChangeListener = c -> updateChartData(offerBookListItems);
@ -66,9 +69,11 @@ class MarketsChartsViewModel extends ActivatableViewModel {
@Override
protected void activate() {
marketPriceFeed.setType(MarketPriceFeed.Type.LAST);
offerBookListItems.addListener(listChangeListener);
offerBook.fillOfferBookListItems();
updateChartData(offerBookListItems);
marketPriceFeed.setCurrencyCode(tradeCurrency.get().getCode());
}
@Override
@ -134,6 +139,7 @@ class MarketsChartsViewModel extends ActivatableViewModel {
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
this.tradeCurrency.set(tradeCurrency);
updateChartData(offerBookListItems);
marketPriceFeed.setCurrencyCode(tradeCurrency.getCode());
}
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -17,6 +17,7 @@
package io.bitsquare.gui.main.offer;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.common.view.ViewLoader;
@ -27,8 +28,8 @@ import javax.inject.Inject;
public class BuyOfferView extends OfferView {
@Inject
public BuyOfferView(ViewLoader viewLoader, Navigation navigation) {
super(viewLoader, navigation);
public BuyOfferView(ViewLoader viewLoader, Navigation navigation, MarketPriceFeed marketPriceFeed) {
super(viewLoader, navigation, marketPriceFeed);
}
@Override

View file

@ -17,6 +17,7 @@
package io.bitsquare.gui.main.offer;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.common.UserThread;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableView;
@ -50,15 +51,16 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
private final ViewLoader viewLoader;
private final Navigation navigation;
private MarketPriceFeed marketPriceFeed;
private final Offer.Direction direction;
private Tab createOfferTab;
private Tab takeOfferTab;
private Tab takeOfferTab, createOfferTab, offerBookTab;
private TradeCurrency tradeCurrency;
private boolean createOfferViewOpen, takeOfferViewOpen;
protected OfferView(ViewLoader viewLoader, Navigation navigation) {
protected OfferView(ViewLoader viewLoader, Navigation navigation, MarketPriceFeed marketPriceFeed) {
this.viewLoader = viewLoader;
this.navigation = navigation;
this.marketPriceFeed = marketPriceFeed;
this.direction = (this instanceof BuyOfferView) ? Offer.Direction.BUY : Offer.Direction.SELL;
}
@ -76,8 +78,19 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
// UserThread.execute needed as focus-out event is called after selectedIndexProperty changed
// TODO Find a way to do that in the InputTextField directly, but a tab change does not trigger any event...
TabPane tabPane = root;
tabPane.getSelectionModel().selectedIndexProperty()
.addListener((observableValue, oldValue, newValue) -> UserThread.execute(InputTextField::hideErrorMessageDisplay));
tabPane.getSelectionModel().selectedItemProperty()
.addListener((observableValue, oldValue, newValue) -> {
UserThread.execute(InputTextField::hideErrorMessageDisplay);
if (newValue != null) {
if (newValue.equals(createOfferTab) && createOfferView != null) {
createOfferView.onTabSelected();
} else if (newValue.equals(takeOfferTab) && takeOfferView != null) {
takeOfferView.onTabSelected();
} else if (newValue.equals(offerBookTab) && offerBookView != null) {
offerBookView.onTabSelected();
}
}
});
// We want to get informed when a tab get closed
tabPane.getTabs().addListener((ListChangeListener<Tab>) change -> {
@ -105,14 +118,17 @@ public abstract class OfferView extends ActivatableView<TabPane, Void> {
private void loadView(Class<? extends View> viewClass) {
TabPane tabPane = root;
View view;
boolean isBuy = direction == Offer.Direction.BUY;
marketPriceFeed.setType(isBuy ? MarketPriceFeed.Type.ASK : MarketPriceFeed.Type.BID);
if (viewClass == OfferBookView.class && offerBookView == null) {
view = viewLoader.load(viewClass);
// Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens.
final Tab tab = new Tab(direction == Offer.Direction.BUY ? "Buy bitcoin" : "Sell bitcoin");
tab.setClosable(false);
tab.setContent(view.getRoot());
tabPane.getTabs().add(tab);
offerBookTab = new Tab(isBuy ? "Buy bitcoin" : "Sell bitcoin");
offerBookTab.setClosable(false);
offerBookTab.setContent(view.getRoot());
tabPane.getTabs().add(offerBookTab);
offerBookView = (OfferBookView) view;
OfferActionHandler offerActionHandler = new OfferActionHandler() {

View file

@ -17,6 +17,7 @@
package io.bitsquare.gui.main.offer;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.common.view.ViewLoader;
@ -27,8 +28,8 @@ import javax.inject.Inject;
public class SellOfferView extends OfferView {
@Inject
public SellOfferView(ViewLoader viewLoader, Navigation navigation) {
super(viewLoader, navigation);
public SellOfferView(ViewLoader viewLoader, Navigation navigation, MarketPriceFeed marketPriceFeed) {
super(viewLoader, navigation, marketPriceFeed);
}
@Override

View file

@ -22,12 +22,10 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.SettableFuture;
import com.google.inject.Inject;
import io.bitsquare.arbitration.Arbitrator;
import io.bitsquare.btc.AddressEntry;
import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.*;
import io.bitsquare.btc.blockchain.BlockchainService;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.common.UserThread;
import io.bitsquare.common.crypto.KeyRing;
import io.bitsquare.gui.common.model.ActivatableDataModel;
@ -72,6 +70,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
private final User user;
private final KeyRing keyRing;
private final P2PService p2PService;
private MarketPriceFeed marketPriceFeed;
private final WalletPasswordPopup walletPasswordPopup;
private BlockchainService blockchainService;
private final BSFormatter formatter;
@ -112,7 +111,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
@Inject
CreateOfferDataModel(OpenOfferManager openOfferManager, WalletService walletService, TradeWalletService tradeWalletService,
Preferences preferences, User user, KeyRing keyRing, P2PService p2PService,
Preferences preferences, User user, KeyRing keyRing, P2PService p2PService, MarketPriceFeed marketPriceFeed,
WalletPasswordPopup walletPasswordPopup, BlockchainService blockchainService, BSFormatter formatter) {
this.openOfferManager = openOfferManager;
this.walletService = walletService;
@ -121,6 +120,7 @@ class CreateOfferDataModel extends ActivatableDataModel {
this.user = user;
this.keyRing = keyRing;
this.p2PService = p2PService;
this.marketPriceFeed = marketPriceFeed;
this.walletPasswordPopup = walletPasswordPopup;
this.blockchainService = blockchainService;
this.formatter = formatter;
@ -223,8 +223,13 @@ class CreateOfferDataModel extends ActivatableDataModel {
PaymentAccount account = user.findFirstPaymentAccountWithCurrency(tradeCurrency);
if (account != null)
paymentAccount = account;
marketPriceFeed.setCurrencyCode(tradeCurrencyCode.get());
}
void onTabSelected() {
marketPriceFeed.setCurrencyCode(tradeCurrencyCode.get());
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions
@ -283,9 +288,12 @@ class CreateOfferDataModel extends ActivatableDataModel {
public void onCurrencySelected(TradeCurrency tradeCurrency) {
if (tradeCurrency != null) {
this.tradeCurrency = tradeCurrency;
tradeCurrencyCode.set(tradeCurrency.getCode());
String code = tradeCurrency.getCode();
tradeCurrencyCode.set(code);
paymentAccount.setSelectedTradeCurrency(tradeCurrency);
marketPriceFeed.setCurrencyCode(code);
}
}
@ -330,24 +338,28 @@ class CreateOfferDataModel extends ActivatableDataModel {
return feeFromFundingTxProperty.get().compareTo(FeePolicy.getMinRequiredFeeForFundingTx()) >= 0;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Utils
///////////////////////////////////////////////////////////////////////////////////////////
private void requestFeeFromBlockchain(String transactionId) {
SettableFuture<Coin> future = blockchainService.requestFeeFromBlockchain(transactionId);
Futures.addCallback(future, new FutureCallback<Coin>() {
public void onSuccess(Coin fee) {
UserThread.execute(() -> feeFromFundingTxProperty.set(fee));
}
if (preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET) {
SettableFuture<Coin> future = blockchainService.requestFee(transactionId);
Futures.addCallback(future, new FutureCallback<Coin>() {
public void onSuccess(Coin fee) {
UserThread.execute(() -> feeFromFundingTxProperty.set(fee));
}
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> new Popup()
.warning("We did not get a response for the request of the mining fee used in the funding transaction.")
.show());
}
});
public void onFailure(@NotNull Throwable throwable) {
UserThread.execute(() -> new Popup()
.warning("We did not get a response for the request of the mining fee used in the funding transaction.")
.show());
}
});
} else {
feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx());
}
}
void calculateVolume() {

View file

@ -201,6 +201,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
this.closeHandler = closeHandler;
}
public void onTabSelected() {
model.dataModel.onTabSelected();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions

View file

@ -105,7 +105,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
@Inject
public CreateOfferViewModel(CreateOfferDataModel dataModel, FiatValidator fiatValidator, BtcValidator btcValidator,
P2PService p2PService,
P2PService p2PService,
BSFormatter formatter) {
super(dataModel);

View file

@ -197,6 +197,10 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
this.offerActionHandler = offerActionHandler;
}
public void onTabSelected() {
model.onTabSelected();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions

View file

@ -19,6 +19,7 @@ package io.bitsquare.gui.main.offer.offerbook;
import com.google.inject.Inject;
import io.bitsquare.app.Version;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.common.handlers.ErrorMessageHandler;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.gui.common.model.ActivatableViewModel;
@ -52,6 +53,7 @@ class OfferBookViewModel extends ActivatableViewModel {
private final OfferBook offerBook;
private final Preferences preferences;
private final P2PService p2PService;
private MarketPriceFeed marketPriceFeed;
final BSFormatter formatter;
private final FilteredList<OfferBookListItem> filteredItems;
@ -72,7 +74,7 @@ class OfferBookViewModel extends ActivatableViewModel {
@Inject
public OfferBookViewModel(User user, OpenOfferManager openOfferManager, OfferBook offerBook,
Preferences preferences, P2PService p2PService,
Preferences preferences, P2PService p2PService, MarketPriceFeed marketPriceFeed,
BSFormatter formatter) {
super();
@ -81,6 +83,7 @@ class OfferBookViewModel extends ActivatableViewModel {
this.offerBook = offerBook;
this.preferences = preferences;
this.p2PService = p2PService;
this.marketPriceFeed = marketPriceFeed;
this.formatter = formatter;
offerBookListItems = offerBook.getOfferBookListItems();
@ -91,6 +94,7 @@ class OfferBookViewModel extends ActivatableViewModel {
tradeCurrency = CurrencyUtil.getDefaultTradeCurrency();
tradeCurrencyCode.set(tradeCurrency.getCode());
marketPriceFeed.setCurrencyCode(tradeCurrencyCode.get());
}
@Override
@ -115,6 +119,10 @@ class OfferBookViewModel extends ActivatableViewModel {
this.direction = direction;
}
void onTabSelected() {
marketPriceFeed.setCurrencyCode(tradeCurrencyCode.get());
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions
@ -122,7 +130,9 @@ class OfferBookViewModel extends ActivatableViewModel {
public void onSetTradeCurrency(TradeCurrency tradeCurrency) {
this.tradeCurrency = tradeCurrency;
tradeCurrencyCode.set(tradeCurrency.getCode());
String code = tradeCurrency.getCode();
tradeCurrencyCode.set(code);
marketPriceFeed.setCurrencyCode(code);
filterList();
}

View file

@ -25,6 +25,7 @@ import io.bitsquare.btc.FeePolicy;
import io.bitsquare.btc.TradeWalletService;
import io.bitsquare.btc.WalletService;
import io.bitsquare.btc.listeners.BalanceListener;
import io.bitsquare.btc.pricefeed.MarketPriceFeed;
import io.bitsquare.common.handlers.ResultHandler;
import io.bitsquare.gui.common.model.ActivatableDataModel;
import io.bitsquare.gui.popups.WalletPasswordPopup;
@ -63,6 +64,7 @@ class TakeOfferDataModel extends ActivatableDataModel {
private final User user;
private final WalletPasswordPopup walletPasswordPopup;
private final Preferences preferences;
private MarketPriceFeed marketPriceFeed;
private final Coin offerFeeAsCoin;
private final Coin networkFeeAsCoin;
@ -90,13 +92,14 @@ class TakeOfferDataModel extends ActivatableDataModel {
@Inject
TakeOfferDataModel(TradeManager tradeManager, TradeWalletService tradeWalletService,
WalletService walletService, User user, WalletPasswordPopup walletPasswordPopup,
Preferences preferences) {
Preferences preferences, MarketPriceFeed marketPriceFeed) {
this.tradeManager = tradeManager;
this.tradeWalletService = tradeWalletService;
this.walletService = walletService;
this.user = user;
this.walletPasswordPopup = walletPasswordPopup;
this.preferences = preferences;
this.marketPriceFeed = marketPriceFeed;
offerFeeAsCoin = FeePolicy.getCreateOfferFee();
networkFeeAsCoin = FeePolicy.getFixedTxFeeForTrades();
@ -152,12 +155,16 @@ class TakeOfferDataModel extends ActivatableDataModel {
};
offer.resetState();
marketPriceFeed.setCurrencyCode(offer.getCurrencyCode());
}
void checkOfferAvailability(ResultHandler resultHandler) {
tradeManager.checkOfferAvailability(offer, resultHandler);
}
void onTabSelected() {
marketPriceFeed.setCurrencyCode(offer.getCurrencyCode());
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions

View file

@ -310,6 +310,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
new Popup().warning("You have already funds paid in.\nIn the <Funds/Open for withdrawal> section you can withdraw those funds.").show();*/
}
public void onTabSelected() {
model.dataModel.onTabSelected();
}
///////////////////////////////////////////////////////////////////////////////////////////
// UI actions
///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -55,24 +55,24 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
@Override
public void initialize() {
addTitledGroupBg(root, gridRow, 3, "Preferences");
addTitledGroupBg(root, gridRow, 4, "Preferences");
tradeCurrencyComboBox = addLabelComboBox(root, gridRow, "Preferred currency:", Layout.FIRST_ROW_DISTANCE).second;
languageComboBox = addLabelComboBox(root, ++gridRow, "Language:").second;
// btcDenominationComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin denomination:").second;
blockExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators by language:", "").second;
// TODO need a bit extra work to separate trade and non trade tx fees before it can be used
/*transactionFeeInputTextField = addLabelInputTextField(root, ++gridRow, "Transaction fee (satoshi/byte):").second;
transactionFeeFocusedListener = (o, oldValue, newValue) -> {
model.onFocusOutTransactionFeeTextField(oldValue, newValue);
};*/
addTitledGroupBg(root, ++gridRow, 5, "Display options", Layout.GROUP_DISTANCE);
addTitledGroupBg(root, ++gridRow, 4, "Display options", Layout.GROUP_DISTANCE);
useAnimationsCheckBox = addLabelCheckBox(root, gridRow, "Use animations:", "", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
useEffectsCheckBox = addLabelCheckBox(root, ++gridRow, "Use effects:", "").second;
showPlaceOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at place offer:", "").second;
showTakeOfferConfirmationCheckBox = addLabelCheckBox(root, ++gridRow, "Show confirmation at take offer:", "").second;
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators by language:", "").second;
}
@Override

View file

@ -261,6 +261,22 @@ public class BSFormatter {
return parseToFiat(input, currencyCode).equals(parseToFiatWith2Decimals(input, currencyCode));
}
public String formatMarketPrice(double price) {
if (price > 0) {
String str = String.valueOf(price);
int decPoint = str.indexOf(".");
if (decPoint > 0) {
while (str.length() < decPoint + 3) {
str += "0";
}
return str.substring(0, decPoint + 3);
} else {
return str;
}
} else {
return "N/A";
}
}
///////////////////////////////////////////////////////////////////////////////////////////
// Other

View file

@ -12,6 +12,7 @@
<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.peers.PeerGroup" level="TRACE"/>
@ -30,7 +31,6 @@
<logger name="io.bitsquare.storage.Storage" level="WARN"/>
<logger name="io.bitsquare.gui.util.Profiler" level="ERROR"/>
<logger name="io.bitsquare.locale.BSResources" level="ERROR"/>
<logger name="io.bitsquare.temp.storage.RemoteStorage" level="WARN"/>
<logger name="io.bitsquare.storage.FileManager" level="WARN"/>