mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-07-23 15:10:41 -04:00
Add "About Bitsquare" screen, add invert price icon
This commit is contained in:
parent
3f5e1296b1
commit
625749534c
13 changed files with 263 additions and 79 deletions
|
@ -8,6 +8,7 @@ import io.bitsquare.app.Log;
|
||||||
import io.bitsquare.btc.pricefeed.providers.BitcoinAveragePriceProvider;
|
import io.bitsquare.btc.pricefeed.providers.BitcoinAveragePriceProvider;
|
||||||
import io.bitsquare.btc.pricefeed.providers.PoloniexPriceProvider;
|
import io.bitsquare.btc.pricefeed.providers.PoloniexPriceProvider;
|
||||||
import io.bitsquare.btc.pricefeed.providers.PriceProvider;
|
import io.bitsquare.btc.pricefeed.providers.PriceProvider;
|
||||||
|
import io.bitsquare.common.Timer;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.common.handlers.FaultHandler;
|
import io.bitsquare.common.handlers.FaultHandler;
|
||||||
import io.bitsquare.locale.CurrencyUtil;
|
import io.bitsquare.locale.CurrencyUtil;
|
||||||
|
@ -24,6 +25,9 @@ import java.util.function.Consumer;
|
||||||
public class PriceFeed {
|
public class PriceFeed {
|
||||||
private static final Logger log = LoggerFactory.getLogger(PriceFeed.class);
|
private static final Logger log = LoggerFactory.getLogger(PriceFeed.class);
|
||||||
|
|
||||||
|
private static final long MIN_PERIOD_BETWEEN_CALLS = 5000;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Enum
|
// Enum
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -40,9 +44,8 @@ public class PriceFeed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long PERIOD_FIAT_SEC = 60;
|
private static final long PERIOD_FIAT_SEC = 2 * 60;
|
||||||
private static final long PERIOD_ALL_FIAT_SEC = 60 * 5;
|
private static final long PERIOD_ALL_FIAT_SEC = 60 * 5;
|
||||||
private static final long PERIOD_CRYPTO_SEC = 60;
|
|
||||||
private static final long PERIOD_ALL_CRYPTO_SEC = 60 * 5;
|
private static final long PERIOD_ALL_CRYPTO_SEC = 60 * 5;
|
||||||
|
|
||||||
private final Map<String, MarketPrice> cache = new HashMap<>();
|
private final Map<String, MarketPrice> cache = new HashMap<>();
|
||||||
|
@ -55,6 +58,11 @@ public class PriceFeed {
|
||||||
private final StringProperty currencyCodeProperty = new SimpleStringProperty();
|
private final StringProperty currencyCodeProperty = new SimpleStringProperty();
|
||||||
private final ObjectProperty<Type> typeProperty = new SimpleObjectProperty<>();
|
private final ObjectProperty<Type> typeProperty = new SimpleObjectProperty<>();
|
||||||
private final IntegerProperty currenciesUpdateFlag = new SimpleIntegerProperty(0);
|
private final IntegerProperty currenciesUpdateFlag = new SimpleIntegerProperty(0);
|
||||||
|
private long bitcoinAveragePriceProviderLastCallAllTs;
|
||||||
|
private long poloniexPriceProviderLastCallAllTs;
|
||||||
|
private long bitcoinAveragePriceProviderLastCallTs;
|
||||||
|
private Timer cryptoCurrenciesTime;
|
||||||
|
private Timer fiatCurrenciesTime;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -76,19 +84,18 @@ public class PriceFeed {
|
||||||
|
|
||||||
requestAllPrices(fiatPriceProvider, () -> {
|
requestAllPrices(fiatPriceProvider, () -> {
|
||||||
applyPrice();
|
applyPrice();
|
||||||
UserThread.runPeriodically(() -> requestPrice(fiatPriceProvider), PERIOD_FIAT_SEC);
|
if (fiatCurrenciesTime == null)
|
||||||
|
fiatCurrenciesTime = UserThread.runPeriodically(() -> requestPrice(fiatPriceProvider), PERIOD_FIAT_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
requestAllPrices(cryptoCurrenciesPriceProvider, () -> {
|
requestAllPrices(cryptoCurrenciesPriceProvider, () -> {
|
||||||
applyPrice();
|
applyPrice();
|
||||||
UserThread.runPeriodically(() -> requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice),
|
if (cryptoCurrenciesTime == null)
|
||||||
PERIOD_CRYPTO_SEC);
|
cryptoCurrenciesTime = UserThread.runPeriodically(() -> requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice),
|
||||||
|
PERIOD_ALL_CRYPTO_SEC);
|
||||||
});
|
});
|
||||||
|
|
||||||
UserThread.runPeriodically(() -> requestAllPrices(fiatPriceProvider, this::applyPrice), PERIOD_ALL_FIAT_SEC);
|
UserThread.runPeriodically(() -> requestAllPrices(fiatPriceProvider, this::applyPrice), PERIOD_ALL_FIAT_SEC);
|
||||||
UserThread.runPeriodically(() -> requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice), PERIOD_ALL_CRYPTO_SEC);
|
|
||||||
|
|
||||||
requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -110,14 +117,18 @@ public class PriceFeed {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrencyCode(String currencyCode) {
|
public void setCurrencyCode(String currencyCode) {
|
||||||
|
if (this.currencyCode != currencyCode) {
|
||||||
this.currencyCode = currencyCode;
|
this.currencyCode = currencyCode;
|
||||||
currencyCodeProperty.set(currencyCode);
|
currencyCodeProperty.set(currencyCode);
|
||||||
applyPrice();
|
applyPrice();
|
||||||
|
|
||||||
if (CurrencyUtil.isFiatCurrency(currencyCode))
|
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
|
||||||
requestPrice(fiatPriceProvider);
|
requestPrice(fiatPriceProvider);
|
||||||
else
|
} else {
|
||||||
requestPrice(cryptoCurrenciesPriceProvider);
|
// Poloniex does not support calls for one currency just for all which is quite a bit of data
|
||||||
|
requestAllPrices(cryptoCurrenciesPriceProvider, this::applyPrice);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,7 +165,6 @@ public class PriceFeed {
|
||||||
if (priceConsumer != null && currencyCode != null && type != null) {
|
if (priceConsumer != null && currencyCode != null && type != null) {
|
||||||
if (cache.containsKey(currencyCode)) {
|
if (cache.containsKey(currencyCode)) {
|
||||||
MarketPrice marketPrice = cache.get(currencyCode);
|
MarketPrice marketPrice = cache.get(currencyCode);
|
||||||
//log.debug("applyPrice type=" + type);
|
|
||||||
if (marketPrice != null)
|
if (marketPrice != null)
|
||||||
priceConsumer.accept(marketPrice.getPrice(type));
|
priceConsumer.accept(marketPrice.getPrice(type));
|
||||||
} else {
|
} else {
|
||||||
|
@ -168,13 +178,20 @@ public class PriceFeed {
|
||||||
|
|
||||||
private void requestPrice(PriceProvider provider) {
|
private void requestPrice(PriceProvider provider) {
|
||||||
Log.traceCall();
|
Log.traceCall();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
boolean allowed = false;
|
||||||
|
if (now - bitcoinAveragePriceProviderLastCallTs > MIN_PERIOD_BETWEEN_CALLS) {
|
||||||
|
bitcoinAveragePriceProviderLastCallTs = now;
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowed) {
|
||||||
GetPriceRequest getPriceRequest = new GetPriceRequest();
|
GetPriceRequest getPriceRequest = new GetPriceRequest();
|
||||||
SettableFuture<MarketPrice> future = getPriceRequest.requestPrice(currencyCode, provider);
|
SettableFuture<MarketPrice> future = getPriceRequest.requestPrice(currencyCode, provider);
|
||||||
Futures.addCallback(future, new FutureCallback<MarketPrice>() {
|
Futures.addCallback(future, new FutureCallback<MarketPrice>() {
|
||||||
public void onSuccess(MarketPrice marketPrice) {
|
public void onSuccess(MarketPrice marketPrice) {
|
||||||
UserThread.execute(() -> {
|
UserThread.execute(() -> {
|
||||||
cache.put(marketPrice.currencyCode, marketPrice);
|
cache.put(marketPrice.currencyCode, marketPrice);
|
||||||
//log.debug("marketPrice updated " + marketPrice);
|
|
||||||
priceConsumer.accept(marketPrice.getPrice(type));
|
priceConsumer.accept(marketPrice.getPrice(type));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -183,10 +200,27 @@ public class PriceFeed {
|
||||||
log.debug("Could not load marketPrice\n" + throwable.getMessage());
|
log.debug("Could not load marketPrice\n" + throwable.getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
log.debug("Ignore request. Too many attempt to call the API provider " + provider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void requestAllPrices(PriceProvider provider, @Nullable Runnable resultHandler) {
|
private void requestAllPrices(PriceProvider provider, @Nullable Runnable resultHandler) {
|
||||||
Log.traceCall();
|
Log.traceCall();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
boolean allowed = false;
|
||||||
|
if (provider instanceof BitcoinAveragePriceProvider) {
|
||||||
|
if (now - bitcoinAveragePriceProviderLastCallAllTs > MIN_PERIOD_BETWEEN_CALLS) {
|
||||||
|
bitcoinAveragePriceProviderLastCallAllTs = now;
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
} else if (provider instanceof PoloniexPriceProvider) {
|
||||||
|
if (now - poloniexPriceProviderLastCallAllTs > MIN_PERIOD_BETWEEN_CALLS) {
|
||||||
|
poloniexPriceProviderLastCallAllTs = now;
|
||||||
|
allowed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allowed) {
|
||||||
GetPriceRequest getPriceRequest = new GetPriceRequest();
|
GetPriceRequest getPriceRequest = new GetPriceRequest();
|
||||||
SettableFuture<Map<String, MarketPrice>> future = getPriceRequest.requestAllPrices(provider);
|
SettableFuture<Map<String, MarketPrice>> future = getPriceRequest.requestAllPrices(provider);
|
||||||
Futures.addCallback(future, new FutureCallback<Map<String, MarketPrice>>() {
|
Futures.addCallback(future, new FutureCallback<Map<String, MarketPrice>>() {
|
||||||
|
@ -202,5 +236,8 @@ public class PriceFeed {
|
||||||
UserThread.execute(() -> faultHandler.handleFault("Could not load marketPrices", throwable));
|
UserThread.execute(() -> faultHandler.handleFault("Could not load marketPrices", throwable));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
log.debug("Ignore request. Too many attempt to call the API provider " + provider);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1003,6 +1003,7 @@ textfield */
|
||||||
#price-feed-combo {
|
#price-feed-combo {
|
||||||
-fx-background-color: #555;
|
-fx-background-color: #555;
|
||||||
-fx-text-fill: white;
|
-fx-text-fill: white;
|
||||||
|
-fx-alignment: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#invert-market-price {
|
#invert-market-price {
|
||||||
|
|
|
@ -212,6 +212,12 @@
|
||||||
-fx-image: url("../../../images/link.png");
|
-fx-image: url("../../../images/link.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#invert {
|
||||||
|
-fx-image: url("../../../images/invert.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#avatar_1 {
|
#avatar_1 {
|
||||||
-fx-image: url("../../../images/avatars/avatar_1.png");
|
-fx-image: url("../../../images/avatars/avatar_1.png");
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,6 @@
|
||||||
|
|
||||||
package io.bitsquare.gui.main;
|
package io.bitsquare.gui.main;
|
||||||
|
|
||||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
|
||||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
|
||||||
import io.bitsquare.BitsquareException;
|
import io.bitsquare.BitsquareException;
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
import io.bitsquare.btc.pricefeed.PriceFeed;
|
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||||
|
@ -266,6 +264,7 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
@Override
|
@Override
|
||||||
protected void updateItem(PriceFeedComboBoxItem item, boolean empty) {
|
protected void updateItem(PriceFeedComboBoxItem item, boolean empty) {
|
||||||
super.updateItem(item, empty);
|
super.updateItem(item, empty);
|
||||||
|
|
||||||
if (!empty && item != null) {
|
if (!empty && item != null) {
|
||||||
textProperty().bind(item.displayStringProperty);
|
textProperty().bind(item.displayStringProperty);
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,18 +286,19 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||||
buttonCell.setId("price-feed-combo");
|
buttonCell.setId("price-feed-combo");
|
||||||
priceComboBox.setButtonCell(buttonCell);
|
priceComboBox.setButtonCell(buttonCell);
|
||||||
|
|
||||||
Label invertIcon = new Label();
|
|
||||||
HBox.setMargin(invertIcon, new Insets(3, 0, 0, 0));
|
final ImageView invertIcon = new ImageView();
|
||||||
invertIcon.setId("invert-market-price");
|
invertIcon.setId("invert");
|
||||||
invertIcon.setOpacity(0.8);
|
final Button invertIconButton = new Button("", invertIcon);
|
||||||
invertIcon.setOnMouseClicked(e -> {
|
invertIconButton.setPadding(new Insets(0, 0, 0, 0));
|
||||||
model.preferences.flipUseInvertedMarketPrice();
|
invertIconButton.setFocusTraversable(false);
|
||||||
});
|
invertIconButton.setStyle("-fx-background-color: transparent;");
|
||||||
|
//invertIconButton.setStyle("-fx-focus-color: transparent; -fx-border-radius: 0 2 2 0; -fx-border-color: #aaa; -fx-border-insets: 0 0 0 -1; -fx-border-style: solid solid solid none; -fx-padding: 1 0 1 0;");
|
||||||
|
HBox.setMargin(invertIconButton, new Insets(2, 0, 0, 0));
|
||||||
|
invertIconButton.setOnAction(e -> model.preferences.flipUseInvertedMarketPrice());
|
||||||
|
|
||||||
HBox hBox = new HBox();
|
HBox hBox = new HBox();
|
||||||
hBox.setSpacing(5);
|
hBox.getChildren().setAll(priceComboBox, invertIconButton);
|
||||||
AwesomeDude.setIcon(invertIcon, AwesomeIcon.RETWEET, "14.0");
|
|
||||||
hBox.getChildren().setAll(priceComboBox, invertIcon);
|
|
||||||
|
|
||||||
Label label = new Label(text);
|
Label label = new Label(text);
|
||||||
label.setId("nav-balance-label");
|
label.setId("nav-balance-label");
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
package io.bitsquare.gui.main.overlays.windows;
|
package io.bitsquare.gui.main.overlays.windows;
|
||||||
|
|
||||||
import io.bitsquare.alert.Alert;
|
import io.bitsquare.alert.Alert;
|
||||||
import io.bitsquare.common.util.Utilities;
|
|
||||||
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||||
import io.bitsquare.gui.main.overlays.Overlay;
|
import io.bitsquare.gui.main.overlays.Overlay;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
|
@ -73,8 +72,7 @@ public class DisplayAlertMessageWindow extends Overlay<DisplayAlertMessageWindow
|
||||||
headLineLabel.setStyle("-fx-text-fill: -fx-accent; -fx-font-weight: bold; -fx-font-size: 22;");
|
headLineLabel.setStyle("-fx-text-fill: -fx-accent; -fx-font-weight: bold; -fx-font-size: 22;");
|
||||||
String url = "https://github.com/bitsquare/bitsquare/releases";
|
String url = "https://github.com/bitsquare/bitsquare/releases";
|
||||||
HyperlinkWithIcon hyperlinkWithIcon = addLabelHyperlinkWithIcon(gridPane, ++rowIndex,
|
HyperlinkWithIcon hyperlinkWithIcon = addLabelHyperlinkWithIcon(gridPane, ++rowIndex,
|
||||||
"Download:", url).second;
|
"Download:", url, url).second;
|
||||||
hyperlinkWithIcon.setOnAction(e -> Utilities.openWebPage(url));
|
|
||||||
hyperlinkWithIcon.setMaxWidth(550);
|
hyperlinkWithIcon.setMaxWidth(550);
|
||||||
} else {
|
} else {
|
||||||
headLine = "Important information!";
|
headLine = "Important information!";
|
||||||
|
|
|
@ -2,8 +2,6 @@ package io.bitsquare.gui.main.overlays.windows;
|
||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
import io.bitsquare.common.util.Utilities;
|
|
||||||
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
|
||||||
import io.bitsquare.gui.main.overlays.Overlay;
|
import io.bitsquare.gui.main.overlays.Overlay;
|
||||||
import io.bitsquare.user.Preferences;
|
import io.bitsquare.user.Preferences;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -53,9 +51,7 @@ public class TacWindow extends Overlay<TacWindow> {
|
||||||
@Override
|
@Override
|
||||||
protected void addMessage() {
|
protected void addMessage() {
|
||||||
super.addMessage();
|
super.addMessage();
|
||||||
String url = "https://bitsquare.io/arbitration_system.pdf";
|
addHyperlinkWithIcon(gridPane, ++rowIndex, "Arbitration system", "https://bitsquare.io/arbitration_system.pdf", -6);
|
||||||
HyperlinkWithIcon hyperlinkWithIcon = addHyperlinkWithIcon(gridPane, ++rowIndex, url, -8);
|
|
||||||
hyperlinkWithIcon.setOnAction(e -> Utilities.openWebPage(url));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -27,4 +27,5 @@
|
||||||
|
|
||||||
<Tab fx:id="preferencesTab" text="Settings" closable="false"/>
|
<Tab fx:id="preferencesTab" text="Settings" closable="false"/>
|
||||||
<Tab fx:id="networkSettingsTab" text="Network info" closable="false"/>
|
<Tab fx:id="networkSettingsTab" text="Network info" closable="false"/>
|
||||||
|
<Tab fx:id="aboutTab" text="About" closable="false"/>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
|
|
@ -21,6 +21,7 @@ import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.common.model.Activatable;
|
import io.bitsquare.gui.common.model.Activatable;
|
||||||
import io.bitsquare.gui.common.view.*;
|
import io.bitsquare.gui.common.view.*;
|
||||||
import io.bitsquare.gui.main.MainView;
|
import io.bitsquare.gui.main.MainView;
|
||||||
|
import io.bitsquare.gui.main.settings.about.AboutView;
|
||||||
import io.bitsquare.gui.main.settings.network.NetworkSettingsView;
|
import io.bitsquare.gui.main.settings.network.NetworkSettingsView;
|
||||||
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
import io.bitsquare.gui.main.settings.preferences.PreferencesView;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
|
@ -33,7 +34,7 @@ import javax.inject.Inject;
|
||||||
@FxmlView
|
@FxmlView
|
||||||
public class SettingsView extends ActivatableViewAndModel<TabPane, Activatable> {
|
public class SettingsView extends ActivatableViewAndModel<TabPane, Activatable> {
|
||||||
@FXML
|
@FXML
|
||||||
Tab preferencesTab, networkSettingsTab;
|
Tab preferencesTab, networkSettingsTab, aboutTab;
|
||||||
private final ViewLoader viewLoader;
|
private final ViewLoader viewLoader;
|
||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private Navigation.Listener navigationListener;
|
private Navigation.Listener navigationListener;
|
||||||
|
@ -57,6 +58,8 @@ public class SettingsView extends ActivatableViewAndModel<TabPane, Activatable>
|
||||||
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
||||||
else if (newValue == networkSettingsTab)
|
else if (newValue == networkSettingsTab)
|
||||||
navigation.navigateTo(MainView.class, SettingsView.class, NetworkSettingsView.class);
|
navigation.navigateTo(MainView.class, SettingsView.class, NetworkSettingsView.class);
|
||||||
|
else if (newValue == aboutTab)
|
||||||
|
navigation.navigateTo(MainView.class, SettingsView.class, AboutView.class);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,10 +68,13 @@ public class SettingsView extends ActivatableViewAndModel<TabPane, Activatable>
|
||||||
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
|
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
|
||||||
navigation.addListener(navigationListener);
|
navigation.addListener(navigationListener);
|
||||||
|
|
||||||
if (root.getSelectionModel().getSelectedItem() == preferencesTab)
|
Tab selectedItem = root.getSelectionModel().getSelectedItem();
|
||||||
|
if (selectedItem == preferencesTab)
|
||||||
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
navigation.navigateTo(MainView.class, SettingsView.class, PreferencesView.class);
|
||||||
else
|
else if (selectedItem == networkSettingsTab)
|
||||||
navigation.navigateTo(MainView.class, SettingsView.class, NetworkSettingsView.class);
|
navigation.navigateTo(MainView.class, SettingsView.class, NetworkSettingsView.class);
|
||||||
|
else if (selectedItem == aboutTab)
|
||||||
|
navigation.navigateTo(MainView.class, SettingsView.class, AboutView.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,6 +89,7 @@ public class SettingsView extends ActivatableViewAndModel<TabPane, Activatable>
|
||||||
|
|
||||||
if (view instanceof PreferencesView) tab = preferencesTab;
|
if (view instanceof PreferencesView) tab = preferencesTab;
|
||||||
else if (view instanceof NetworkSettingsView) tab = networkSettingsTab;
|
else if (view instanceof NetworkSettingsView) tab = networkSettingsTab;
|
||||||
|
else if (view instanceof AboutView) tab = aboutTab;
|
||||||
else throw new IllegalArgumentException("Navigation to " + viewClass + " is not supported");
|
else throw new IllegalArgumentException("Navigation to " + viewClass + " is not supported");
|
||||||
|
|
||||||
tab.setContent(view.getRoot());
|
tab.setContent(view.getRoot());
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?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.*?>
|
||||||
|
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.settings.about.AboutView"
|
||||||
|
hgap="5.0" vgap="5.0"
|
||||||
|
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="25.0" top="30.0" right="25"/>
|
||||||
|
</padding>
|
||||||
|
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" halignment="RIGHT"/>
|
||||||
|
<ColumnConstraints hgrow="ALWAYS"/>
|
||||||
|
</columnConstraints>
|
||||||
|
</GridPane>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* 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.gui.main.settings.about;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Version;
|
||||||
|
import io.bitsquare.gui.common.model.Activatable;
|
||||||
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
|
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||||
|
import io.bitsquare.gui.components.TitledGroupBg;
|
||||||
|
import io.bitsquare.gui.util.Layout;
|
||||||
|
import javafx.geometry.HPos;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||||
|
|
||||||
|
@FxmlView
|
||||||
|
public class AboutView extends ActivatableViewAndModel<GridPane, Activatable> {
|
||||||
|
|
||||||
|
private int gridRow = 0;
|
||||||
|
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public AboutView() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 4, "About Bitsquare");
|
||||||
|
GridPane.setColumnSpan(titledGroupBg, 2);
|
||||||
|
Label label = addLabel(root, gridRow, "Bitsquare is an open source project and a decentralized network of users who want to " +
|
||||||
|
"exchange Bitcoin with national currencies or alternative crypto currencies in a privacy protecting way.\n" +
|
||||||
|
"Learn more about Bitsquare on our project web page.", Layout.FIRST_ROW_DISTANCE);
|
||||||
|
label.setWrapText(true);
|
||||||
|
GridPane.setColumnSpan(label, 2);
|
||||||
|
GridPane.setHalignment(label, HPos.LEFT);
|
||||||
|
HyperlinkWithIcon hyperlinkWithIcon = addHyperlinkWithIcon(root, ++gridRow, "Bitsquare web page", "https://bitsquare.io");
|
||||||
|
GridPane.setColumnSpan(hyperlinkWithIcon, 2);
|
||||||
|
hyperlinkWithIcon = addHyperlinkWithIcon(root, ++gridRow, "Source code", "https://github.com/bitsquare/bitsquare");
|
||||||
|
GridPane.setColumnSpan(hyperlinkWithIcon, 2);
|
||||||
|
hyperlinkWithIcon = addHyperlinkWithIcon(root, ++gridRow, "AGPL License", "https://github.com/bitsquare/bitsquare/blob/master/LICENSE");
|
||||||
|
GridPane.setColumnSpan(hyperlinkWithIcon, 2);
|
||||||
|
|
||||||
|
titledGroupBg = addTitledGroupBg(root, ++gridRow, 3, "Support Bitsquare", Layout.GROUP_DISTANCE);
|
||||||
|
GridPane.setColumnSpan(titledGroupBg, 2);
|
||||||
|
label = addLabel(root, gridRow, "Bitsquare is not a company but a community project and open for participation. If you want to participate check out our web page.", Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
label.setWrapText(true);
|
||||||
|
GridPane.setColumnSpan(label, 2);
|
||||||
|
GridPane.setHalignment(label, HPos.LEFT);
|
||||||
|
hyperlinkWithIcon = addHyperlinkWithIcon(root, ++gridRow, "Contribute", "https://bitsquare.io/contribute");
|
||||||
|
GridPane.setColumnSpan(hyperlinkWithIcon, 2);
|
||||||
|
hyperlinkWithIcon = addHyperlinkWithIcon(root, ++gridRow, "Donate", "https://bitsquare.io/contribute/#donation");
|
||||||
|
GridPane.setColumnSpan(hyperlinkWithIcon, 2);
|
||||||
|
|
||||||
|
titledGroupBg = addTitledGroupBg(root, ++gridRow, 3, "Market price API providers", Layout.GROUP_DISTANCE);
|
||||||
|
GridPane.setColumnSpan(titledGroupBg, 2);
|
||||||
|
label = addLabel(root, gridRow, "Bitsquare uses market price feed providers for displaying the current exchange rate.", Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
label.setWrapText(true);
|
||||||
|
GridPane.setColumnSpan(label, 2);
|
||||||
|
GridPane.setHalignment(label, HPos.LEFT);
|
||||||
|
addLabelHyperlinkWithIcon(root, ++gridRow, "Market price API provider for fiat: ", "BitcoinAverage", "https://bitcoinaverage.com");
|
||||||
|
addLabelHyperlinkWithIcon(root, ++gridRow, "Market price API provider for altcoins: ", "Poloniex", "http://poloniex.com");
|
||||||
|
|
||||||
|
titledGroupBg = addTitledGroupBg(root, ++gridRow, 2, "Version details", Layout.GROUP_DISTANCE);
|
||||||
|
GridPane.setColumnSpan(titledGroupBg, 2);
|
||||||
|
addLabelTextField(root, gridRow, "Application version:", Version.VERSION, Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||||
|
addLabelTextField(root, ++gridRow, "Versions of subsystems:",
|
||||||
|
"Network version: " + Version.P2P_NETWORK_VERSION +
|
||||||
|
"; P2P message version: " + Version.getP2PMessageVersion() +
|
||||||
|
"; Local DB version: " + Version.LOCAL_DB_VERSION +
|
||||||
|
"; Trade protocol version: " + Version.TRADE_PROTOCOL_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void activate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deactivate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||||
import io.bitsquare.common.util.Tuple2;
|
import io.bitsquare.common.util.Tuple2;
|
||||||
import io.bitsquare.common.util.Tuple3;
|
import io.bitsquare.common.util.Tuple3;
|
||||||
import io.bitsquare.common.util.Tuple4;
|
import io.bitsquare.common.util.Tuple4;
|
||||||
|
import io.bitsquare.common.util.Utilities;
|
||||||
import io.bitsquare.gui.components.*;
|
import io.bitsquare.gui.components.*;
|
||||||
import javafx.geometry.HPos;
|
import javafx.geometry.HPos;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
|
@ -162,12 +163,14 @@ public class FormBuilder {
|
||||||
// HyperlinkWithIcon
|
// HyperlinkWithIcon
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public static HyperlinkWithIcon addHyperlinkWithIcon(GridPane gridPane, int rowIndex, String url) {
|
|
||||||
return addHyperlinkWithIcon(gridPane, rowIndex, url, 0);
|
public static HyperlinkWithIcon addHyperlinkWithIcon(GridPane gridPane, int rowIndex, String title, String url) {
|
||||||
|
return addHyperlinkWithIcon(gridPane, rowIndex, title, url, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HyperlinkWithIcon addHyperlinkWithIcon(GridPane gridPane, int rowIndex, String url, double top) {
|
public static HyperlinkWithIcon addHyperlinkWithIcon(GridPane gridPane, int rowIndex, String title, String url, double top) {
|
||||||
HyperlinkWithIcon hyperlinkWithIcon = new HyperlinkWithIcon(url, AwesomeIcon.EXTERNAL_LINK);
|
HyperlinkWithIcon hyperlinkWithIcon = new HyperlinkWithIcon(title, AwesomeIcon.EXTERNAL_LINK);
|
||||||
|
hyperlinkWithIcon.setOnAction(e -> Utilities.openWebPage(url));
|
||||||
GridPane.setRowIndex(hyperlinkWithIcon, rowIndex);
|
GridPane.setRowIndex(hyperlinkWithIcon, rowIndex);
|
||||||
GridPane.setColumnIndex(hyperlinkWithIcon, 0);
|
GridPane.setColumnIndex(hyperlinkWithIcon, 0);
|
||||||
GridPane.setMargin(hyperlinkWithIcon, new Insets(top, 0, 0, -4));
|
GridPane.setMargin(hyperlinkWithIcon, new Insets(top, 0, 0, -4));
|
||||||
|
@ -180,18 +183,15 @@ public class FormBuilder {
|
||||||
// Label + HyperlinkWithIcon
|
// Label + HyperlinkWithIcon
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public static Tuple2<Label, HyperlinkWithIcon> addLabelHyperlinkWithIcon(GridPane gridPane, int rowIndex, String title) {
|
public static Tuple2<Label, HyperlinkWithIcon> addLabelHyperlinkWithIcon(GridPane gridPane, int rowIndex, String labelTitle, String title, String url) {
|
||||||
return addLabelHyperlinkWithIcon(gridPane, rowIndex, title, "", 0);
|
return addLabelHyperlinkWithIcon(gridPane, rowIndex, labelTitle, title, url, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Tuple2<Label, HyperlinkWithIcon> addLabelHyperlinkWithIcon(GridPane gridPane, int rowIndex, String title, String url) {
|
public static Tuple2<Label, HyperlinkWithIcon> addLabelHyperlinkWithIcon(GridPane gridPane, int rowIndex, String labelTitle, String title, String url, double top) {
|
||||||
return addLabelHyperlinkWithIcon(gridPane, rowIndex, title, url, 0);
|
Label label = addLabel(gridPane, rowIndex, labelTitle, top);
|
||||||
}
|
|
||||||
|
|
||||||
public static Tuple2<Label, HyperlinkWithIcon> addLabelHyperlinkWithIcon(GridPane gridPane, int rowIndex, String title, String url, double top) {
|
HyperlinkWithIcon hyperlinkWithIcon = new HyperlinkWithIcon(title, AwesomeIcon.EXTERNAL_LINK);
|
||||||
Label label = addLabel(gridPane, rowIndex, title, top);
|
hyperlinkWithIcon.setOnAction(e -> Utilities.openWebPage(url));
|
||||||
|
|
||||||
HyperlinkWithIcon hyperlinkWithIcon = new HyperlinkWithIcon(url, AwesomeIcon.EXTERNAL_LINK);
|
|
||||||
GridPane.setRowIndex(hyperlinkWithIcon, rowIndex);
|
GridPane.setRowIndex(hyperlinkWithIcon, rowIndex);
|
||||||
GridPane.setColumnIndex(hyperlinkWithIcon, 1);
|
GridPane.setColumnIndex(hyperlinkWithIcon, 1);
|
||||||
GridPane.setMargin(hyperlinkWithIcon, new Insets(top, 0, 0, -4));
|
GridPane.setMargin(hyperlinkWithIcon, new Insets(top, 0, 0, -4));
|
||||||
|
|
BIN
gui/src/main/resources/images/invert.png
Normal file
BIN
gui/src/main/resources/images/invert.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 617 B |
BIN
gui/src/main/resources/images/invert@2x.png
Normal file
BIN
gui/src/main/resources/images/invert@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 620 B |
Loading…
Add table
Add a link
Reference in a new issue