mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Use BlockdownloadPane from wallettemplate
This commit is contained in:
parent
2eb5428ed9
commit
e2cdc517e4
@ -95,14 +95,20 @@ class AddressBasedCoinSelector extends DefaultCoinSelector {
|
||||
// TODO It might be risky to accept 0 confirmation tx from the network with only > 1 numBroadcastPeers
|
||||
// Need to be tested in testnet and mainnet
|
||||
// We need to handle cases when malleability happens or tx get lost and have not been successful propagated
|
||||
return type.equals(TransactionConfidence.ConfidenceType.BUILDING) ||
|
||||
/* return type.equals(TransactionConfidence.ConfidenceType.BUILDING) ||
|
||||
type.equals(TransactionConfidence.ConfidenceType.PENDING) &&
|
||||
// we accept network tx without confirmations and numBroadcastPeers > 0
|
||||
/*confidence.getSource().equals(TransactionConfidence.Source.SELF) &&*/
|
||||
//confidence.getSource().equals(TransactionConfidence.Source.SELF) &&
|
||||
// In regtest mode we expect to have only one peer, so we won't see transactions propagate.
|
||||
// TODO: The value 1 below dates from a time when transactions we broadcast *to* were
|
||||
// counted, set to 0
|
||||
(confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get());
|
||||
(confidence.numBroadcastPeers() > 1 || tx.getParams() == RegTestParams.get());*/
|
||||
|
||||
log.debug("numBroadcastPeers = " + confidence.numBroadcastPeers());
|
||||
// TODO at testnet we got confidence.numBroadcastPeers()=1
|
||||
return type.equals(TransactionConfidence.ConfidenceType.BUILDING) ||
|
||||
type.equals(TransactionConfidence.ConfidenceType.PENDING) &&
|
||||
(confidence.numBroadcastPeers() > 0 || tx.getParams() == RegTestParams.get());
|
||||
}
|
||||
|
||||
private static boolean isInBlockChain(Transaction tx) {
|
||||
|
@ -46,6 +46,7 @@ import org.bitcoinj.crypto.TransactionSignature;
|
||||
import org.bitcoinj.kits.WalletAppKit;
|
||||
import org.bitcoinj.params.MainNetParams;
|
||||
import org.bitcoinj.params.RegTestParams;
|
||||
import org.bitcoinj.params.TestNet3Params;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.script.ScriptBuilder;
|
||||
import org.bitcoinj.utils.Threading;
|
||||
@ -54,13 +55,13 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.Service;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@ -102,7 +103,7 @@ public class WalletFacade {
|
||||
private final FeePolicy feePolicy;
|
||||
private final CryptoFacade cryptoFacade;
|
||||
private final Persistence persistence;
|
||||
private final List<DownloadListener> downloadListeners = new CopyOnWriteArrayList<>();
|
||||
// private final List<DownloadListener> downloadListeners = new CopyOnWriteArrayList<>();
|
||||
private final List<AddressConfidenceListener> addressConfidenceListeners = new CopyOnWriteArrayList<>();
|
||||
private final List<TxConfidenceListener> txConfidenceListeners = new CopyOnWriteArrayList<>();
|
||||
private final List<BalanceListener> balanceListeners = new CopyOnWriteArrayList<>();
|
||||
@ -132,7 +133,7 @@ public class WalletFacade {
|
||||
// Public Methods
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public void initialize(StartupListener startupListener) {
|
||||
public void initialize(org.bitcoinj.core.DownloadListener downloadListener, StartupListener startupListener) {
|
||||
// Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means
|
||||
// we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener
|
||||
// we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in
|
||||
@ -164,7 +165,7 @@ public class WalletFacade {
|
||||
// Checkpoint files are made using the BuildCheckpoints tool and usually we have to download the
|
||||
// last months worth or more (takes a few seconds).
|
||||
try {
|
||||
walletAppKit.setCheckpoints(getClass().getClassLoader().getResourceAsStream("wallet/checkpoints"));
|
||||
walletAppKit.setCheckpoints(getClass().getResourceAsStream("wallet/checkpoints"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
@ -172,24 +173,40 @@ public class WalletFacade {
|
||||
// As an example!
|
||||
// walletAppKit.useTor();
|
||||
}
|
||||
walletAppKit.setDownloadListener(new BlockChainDownloadListener())
|
||||
else if (params == TestNet3Params.get()) {
|
||||
walletAppKit.setCheckpoints(getClass().getResourceAsStream("wallet/checkpoints.testnet"));
|
||||
//walletAppKit.useTor();
|
||||
}
|
||||
walletAppKit.setDownloadListener(downloadListener)
|
||||
.setBlockingStartup(false)
|
||||
.restoreWalletFromSeed(null)
|
||||
.setUserAgent("BitSquare", "0.1");
|
||||
|
||||
/*
|
||||
// TODO restore from DeterministicSeed
|
||||
if (seed != null)
|
||||
walletAppKit.restoreWalletFromSeed(seed);
|
||||
*/
|
||||
|
||||
walletAppKit.addListener(new Service.Listener() {
|
||||
@Override
|
||||
public void failed(Service.State from, Throwable failure) {
|
||||
walletAppKit = null;
|
||||
// TODO show error popup
|
||||
//crashAlert(failure);
|
||||
}
|
||||
}, Threading.SAME_THREAD);
|
||||
walletAppKit.startAsync();
|
||||
}
|
||||
|
||||
private void initWallet() {
|
||||
wallet = walletAppKit.wallet();
|
||||
|
||||
wallet.allowSpendingUnconfirmedTransactions();
|
||||
//walletAppKit.peerGroup().setMaxConnections(11);
|
||||
|
||||
if (params == RegTestParams.get())
|
||||
/* if (params == RegTestParams.get())
|
||||
walletAppKit.peerGroup().setMinBroadcastConnections(1);
|
||||
else
|
||||
walletAppKit.peerGroup().setMinBroadcastConnections(3);
|
||||
walletAppKit.peerGroup().setMinBroadcastConnections(3);*/
|
||||
|
||||
|
||||
walletEventListener = new WalletEventListener() {
|
||||
@ -266,14 +283,14 @@ public class WalletFacade {
|
||||
// Listener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public DownloadListener addDownloadListener(DownloadListener listener) {
|
||||
/* public DownloadListener addDownloadListener(DownloadListener listener) {
|
||||
downloadListeners.add(listener);
|
||||
return listener;
|
||||
}
|
||||
|
||||
public void removeDownloadListener(DownloadListener listener) {
|
||||
downloadListeners.remove(listener);
|
||||
}
|
||||
}*/
|
||||
|
||||
public AddressConfidenceListener addAddressConfidenceListener(AddressConfidenceListener listener) {
|
||||
addressConfidenceListeners.add(listener);
|
||||
@ -1140,7 +1157,7 @@ public class WalletFacade {
|
||||
void downloadComplete();
|
||||
}
|
||||
|
||||
private class BlockChainDownloadListener extends org.bitcoinj.core.DownloadListener {
|
||||
/* private class BlockChainDownloadListener extends org.bitcoinj.core.DownloadListener {
|
||||
@Override
|
||||
protected void progress(double percent, int blocksSoFar, Date date) {
|
||||
super.progress(percent, blocksSoFar, date);
|
||||
@ -1164,6 +1181,6 @@ public class WalletFacade {
|
||||
downloadListener.downloadComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
|
@ -146,8 +146,8 @@ class NetworkParametersProvider implements Provider<NetworkParameters> {
|
||||
|
||||
// Set default
|
||||
// String networkType= WalletFacade.MAIN_NET;
|
||||
// String networkType = WalletFacade.TEST_NET;
|
||||
String networkType = WalletFacade.REG_TEST_NET;
|
||||
String networkType = WalletFacade.TEST_NET;
|
||||
// String networkType = WalletFacade.REG_TEST_NET;
|
||||
|
||||
if (networkTypeFromConfig != null)
|
||||
networkType = networkTypeFromConfig;
|
||||
|
@ -30,8 +30,13 @@ import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
import io.bitsquare.user.User;
|
||||
|
||||
import org.bitcoinj.core.DownloadListener;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
@ -60,8 +65,6 @@ class MainModel extends UIModel {
|
||||
|
||||
final BooleanProperty backendInited = new SimpleBooleanProperty();
|
||||
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty();
|
||||
final BooleanProperty networkSyncComplete = new SimpleBooleanProperty();
|
||||
// final ObjectProperty<Coin> balance = new SimpleObjectProperty<>();
|
||||
final IntegerProperty numPendingTrades = new SimpleIntegerProperty(0);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -142,19 +145,24 @@ class MainModel extends UIModel {
|
||||
|
||||
Profiler.printMsgWithTime("MainModel.initFacades");
|
||||
|
||||
walletFacade.initialize(() -> {
|
||||
DownloadListener downloadListener = new DownloadListener() {
|
||||
@Override
|
||||
protected void progress(double percent, int blocksLeft, Date date) {
|
||||
super.progress(percent, blocksLeft, date);
|
||||
Platform.runLater(() -> networkSyncProgress.set(percent / 100.0));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doneDownload() {
|
||||
super.doneDownload();
|
||||
Platform.runLater(() -> networkSyncProgress.set(1.0));
|
||||
}
|
||||
};
|
||||
|
||||
walletFacade.initialize(downloadListener, () -> {
|
||||
walletFacadeInited = true;
|
||||
if (messageFacadeInited)
|
||||
onFacadesInitialised();
|
||||
|
||||
|
||||
/* walletFacade.addBalanceListener(new BalanceListener() {
|
||||
@Override
|
||||
public void onBalanceChanged(Coin balance) {
|
||||
updateBalance(balance);
|
||||
}
|
||||
});
|
||||
updateBalance(walletFacade.getWalletBalance());*/
|
||||
});
|
||||
}
|
||||
|
||||
@ -187,19 +195,6 @@ class MainModel extends UIModel {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void onFacadesInitialised() {
|
||||
// TODO Consider to use version sync notification pane from Mike Hearn
|
||||
walletFacade.addDownloadListener(new WalletFacade.DownloadListener() {
|
||||
@Override
|
||||
public void progress(double percent) {
|
||||
networkSyncProgress.set(percent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void downloadComplete() {
|
||||
networkSyncComplete.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
tradeManager.getPendingTrades().addListener((MapChangeListener<String,
|
||||
Trade>) change -> updateNumPendingTrades());
|
||||
updateNumPendingTrades();
|
||||
@ -211,7 +206,4 @@ class MainModel extends UIModel {
|
||||
numPendingTrades.set(tradeManager.getPendingTrades().size());
|
||||
}
|
||||
|
||||
/* private void updateBalance(Coin balance) {
|
||||
this.balance.set(balance);
|
||||
}*/
|
||||
}
|
||||
|
@ -24,9 +24,11 @@ import io.bitsquare.gui.util.BSFormatter;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
@ -40,15 +42,14 @@ import org.slf4j.LoggerFactory;
|
||||
class MainPM extends PresentationModel<MainModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainPM.class);
|
||||
|
||||
private BSFormatter formatter;
|
||||
|
||||
final BooleanProperty backendInited = new SimpleBooleanProperty();
|
||||
// final StringProperty balance = new SimpleStringProperty();
|
||||
final StringProperty bankAccountsComboBoxPrompt = new SimpleStringProperty();
|
||||
final BooleanProperty bankAccountsComboBoxDisable = new SimpleBooleanProperty();
|
||||
final StringProperty splashScreenInfoText = new SimpleStringProperty();
|
||||
final BooleanProperty networkSyncComplete = new SimpleBooleanProperty();
|
||||
final IntegerProperty numPendingTrades = new SimpleIntegerProperty();
|
||||
private BSFormatter formatter;
|
||||
|
||||
final DoubleProperty networkSyncProgress = new SimpleDoubleProperty();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
@ -71,7 +72,7 @@ class MainPM extends PresentationModel<MainModel> {
|
||||
super.initialize();
|
||||
|
||||
backendInited.bind(model.backendInited);
|
||||
networkSyncComplete.bind(model.networkSyncComplete);
|
||||
networkSyncProgress.bind(model.networkSyncProgress);
|
||||
numPendingTrades.bind(model.numPendingTrades);
|
||||
|
||||
model.networkSyncProgress.addListener((ov, oldValue, newValue) -> {
|
||||
@ -84,9 +85,6 @@ class MainPM extends PresentationModel<MainModel> {
|
||||
|
||||
});
|
||||
|
||||
/*model.balance.addListener((ov, oldValue, newValue) -> balance.set(formatter.formatCoinWithCode
|
||||
(newValue)));*/
|
||||
|
||||
model.getBankAccounts().addListener((ListChangeListener<BankAccount>) change -> {
|
||||
bankAccountsComboBoxDisable.set(change.getList().isEmpty());
|
||||
bankAccountsComboBoxPrompt.set(change.getList().isEmpty() ? "No accounts" : "");
|
||||
|
@ -52,6 +52,8 @@ import javafx.scene.paint.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import wallettemplate.controls.NotificationBarPane;
|
||||
|
||||
public class MainViewCB extends ViewCB<MainPM> {
|
||||
private static final Logger log = LoggerFactory.getLogger(MainViewCB.class);
|
||||
|
||||
@ -61,7 +63,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
private final ToggleGroup navButtonsGroup = new ToggleGroup();
|
||||
|
||||
private BorderPane baseApplicationContainer;
|
||||
private VBox baseOverlayContainer;
|
||||
private StackPane baseOverlayContainer;
|
||||
private AnchorPane contentContainer;
|
||||
private HBox leftNavPane, rightNavPane;
|
||||
private NetworkSyncPane networkSyncPane;
|
||||
@ -69,6 +71,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
accountButton;
|
||||
private Pane ordersButtonButtonPane;
|
||||
private Label numPendingTradesLabel;
|
||||
private NotificationBarPane notificationBarPane;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -166,10 +169,24 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
|
||||
private void startup() {
|
||||
baseApplicationContainer = getBaseApplicationContainer();
|
||||
baseOverlayContainer = getSplashScreen();
|
||||
((StackPane) root).getChildren().addAll(baseApplicationContainer, baseOverlayContainer);
|
||||
baseOverlayContainer = new StackPane();
|
||||
|
||||
onBaseContainersCreated();
|
||||
// TODO remove dependency of NotificationBarPane with getSplashScreen (borderPane content)
|
||||
notificationBarPane = new NotificationBarPane(getSplashScreen());
|
||||
baseOverlayContainer.getChildren().add(notificationBarPane);
|
||||
|
||||
final NotificationBarPane.Item syncItem = notificationBarPane.pushItem("Synchronising with the Bitcoin network",
|
||||
presentationModel.networkSyncProgress);
|
||||
|
||||
presentationModel.networkSyncProgress.addListener((ov, oldValue, newValue) -> {
|
||||
if ((double) newValue >= 1.0) {
|
||||
log.debug("### networkSyncProgress " + newValue);
|
||||
syncItem.cancel();
|
||||
onBaseContainersCreated();
|
||||
}
|
||||
});
|
||||
|
||||
((StackPane) root).getChildren().addAll(baseApplicationContainer, baseOverlayContainer);
|
||||
}
|
||||
|
||||
private void onBaseContainersCreated() {
|
||||
@ -284,7 +301,7 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
return borderPane;
|
||||
}
|
||||
|
||||
private VBox getSplashScreen() {
|
||||
private BorderPane getSplashScreen() {
|
||||
VBox vBox = new VBox();
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
vBox.setSpacing(10);
|
||||
@ -303,7 +320,9 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
loadingLabel.textProperty().bind(presentationModel.splashScreenInfoText);
|
||||
|
||||
vBox.getChildren().addAll(logo, subTitle, loadingLabel);
|
||||
return vBox;
|
||||
|
||||
BorderPane borderPane = new BorderPane(vBox);
|
||||
return borderPane;
|
||||
}
|
||||
|
||||
private AnchorPane getApplicationContainer() {
|
||||
@ -333,15 +352,6 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
AnchorPane.setLeftAnchor(networkSyncPane, 0d);
|
||||
AnchorPane.setBottomAnchor(networkSyncPane, 5d);
|
||||
|
||||
// TODO sometimes it keeps running... deactivate ti for the moment and replace it with the notification pane
|
||||
// from Mike Hearn later
|
||||
networkSyncPane.setVisible(false);
|
||||
|
||||
presentationModel.networkSyncComplete.addListener((ov, old, newValue) -> {
|
||||
if (newValue)
|
||||
networkSyncPane.downloadComplete();
|
||||
});
|
||||
|
||||
anchorPane.getChildren().addAll(leftNavPane, rightNavPane, contentContainer, networkSyncPane);
|
||||
return anchorPane;
|
||||
}
|
||||
@ -361,8 +371,6 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
msgButton = addNavButton(msgButtonHolder, "Messages", Navigation.Item.MSG);
|
||||
leftNavPane.getChildren().add(msgButtonHolder);
|
||||
|
||||
//addBalanceInfo(rightNavPane);
|
||||
|
||||
addBankAccountComboBox(rightNavPane);
|
||||
|
||||
settingsButton = addNavButton(rightNavPane, "Preferences", Navigation.Item.SETTINGS);
|
||||
@ -408,28 +416,6 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
return toggleButton;
|
||||
}
|
||||
|
||||
/*private void addBalanceInfo(Pane parent) {
|
||||
final TextField balanceTextField = new TextField();
|
||||
balanceTextField.setEditable(false);
|
||||
balanceTextField.setPrefWidth(110);
|
||||
balanceTextField.setId("nav-balance-label");
|
||||
balanceTextField.textProperty().bind(presentationModel.balance);
|
||||
|
||||
|
||||
final Label titleLabel = new Label("Balance");
|
||||
titleLabel.setMouseTransparent(true);
|
||||
titleLabel.setId("nav-button-label");
|
||||
balanceTextField.widthProperty().addListener((ov, o, n) ->
|
||||
titleLabel.setLayoutX(((double) n - titleLabel.getWidth()) / 2));
|
||||
|
||||
final VBox vBox = new VBox();
|
||||
vBox.setPadding(new Insets(12, 5, 0, 0));
|
||||
vBox.setSpacing(2);
|
||||
vBox.getChildren().setAll(balanceTextField, titleLabel);
|
||||
vBox.setAlignment(Pos.CENTER);
|
||||
parent.getChildren().add(vBox);
|
||||
}*/
|
||||
|
||||
private void addBankAccountComboBox(Pane parent) {
|
||||
final ComboBox<BankAccount> comboBox = new ComboBox<>(presentationModel.getBankAccounts());
|
||||
comboBox.setLayoutY(12);
|
||||
@ -460,4 +446,4 @@ public class MainViewCB extends ViewCB<MainPM> {
|
||||
vBox.getChildren().setAll(comboBox, titleLabel);
|
||||
parent.getChildren().add(vBox);
|
||||
}
|
||||
}
|
||||
}
|
@ -48,7 +48,7 @@ public class BSResources {
|
||||
try {
|
||||
return BSResources.getResourceBundle().getString(key);
|
||||
} catch (MissingResourceException e) {
|
||||
log.warn("MissingResourceException for key: " + key);
|
||||
log.warn("Missing resource for key: " + key);
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
142
src/main/java/wallettemplate/controls/NotificationBarPane.java
Normal file
142
src/main/java/wallettemplate/controls/NotificationBarPane.java
Normal file
@ -0,0 +1,142 @@
|
||||
package wallettemplate.controls;
|
||||
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import javafx.animation.Interpolator;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.value.ObservableDoubleValue;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.scene.*;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import wallettemplate.utils.GuiUtils;
|
||||
import wallettemplate.utils.easing.EasingMode;
|
||||
import wallettemplate.utils.easing.ElasticInterpolator;
|
||||
|
||||
/**
|
||||
* Wraps the given Node in a BorderPane and allows a thin bar to slide in from the bottom or top, squeezing the content
|
||||
* node. The API allows different "items" to be added/removed and they will be displayed one at a time, fading between
|
||||
* them when the topmost is removed. Each item is meant to be used for e.g. a background task and can contain a button
|
||||
* and/or a progress bar.
|
||||
*/
|
||||
public class NotificationBarPane extends BorderPane {
|
||||
public static final Duration ANIM_IN_DURATION = GuiUtils.UI_ANIMATION_TIME.multiply(2);
|
||||
public static final Duration ANIM_OUT_DURATION = GuiUtils.UI_ANIMATION_TIME;
|
||||
|
||||
private HBox bar;
|
||||
private Label label;
|
||||
private double barHeight;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
public class Item {
|
||||
public final SimpleStringProperty label;
|
||||
@Nullable public final ObservableDoubleValue progress;
|
||||
|
||||
public Item(String label, @Nullable ObservableDoubleValue progress) {
|
||||
this.label = new SimpleStringProperty(label);
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
items.remove(this);
|
||||
}
|
||||
}
|
||||
|
||||
public final ObservableList<Item> items;
|
||||
|
||||
public NotificationBarPane(Node content) {
|
||||
super(content);
|
||||
progressBar = new ProgressBar();
|
||||
label = new Label("infobar!");
|
||||
bar = new HBox(label);
|
||||
bar.setMinHeight(0.0);
|
||||
bar.getStyleClass().add("info-bar");
|
||||
bar.setFillHeight(true);
|
||||
setBottom(bar);
|
||||
// Figure out the height of the bar based on the CSS. Must wait until after we've been added to the parent node.
|
||||
sceneProperty().addListener(o -> {
|
||||
if (getParent() == null) return;
|
||||
getParent().applyCss();
|
||||
getParent().layout();
|
||||
barHeight = bar.getHeight();
|
||||
bar.setPrefHeight(0.0);
|
||||
});
|
||||
items = FXCollections.observableArrayList();
|
||||
items.addListener((ListChangeListener<? super Item>) change -> {
|
||||
config();
|
||||
showOrHide();
|
||||
});
|
||||
}
|
||||
|
||||
private void config() {
|
||||
if (items.isEmpty()) return;
|
||||
Item item = items.get(0);
|
||||
|
||||
bar.getChildren().clear();
|
||||
label.textProperty().bind(item.label);
|
||||
label.setMaxWidth(Double.MAX_VALUE);
|
||||
HBox.setHgrow(label, Priority.ALWAYS);
|
||||
bar.getChildren().add(label);
|
||||
if (item.progress != null) {
|
||||
progressBar.setMinWidth(200);
|
||||
progressBar.progressProperty().bind(item.progress);
|
||||
bar.getChildren().add(progressBar);
|
||||
}
|
||||
}
|
||||
|
||||
private void showOrHide() {
|
||||
if (items.isEmpty())
|
||||
animateOut();
|
||||
else
|
||||
animateIn();
|
||||
}
|
||||
|
||||
public boolean isShowing() {
|
||||
return bar.getPrefHeight() > 0;
|
||||
}
|
||||
|
||||
private void animateIn() {
|
||||
animate(barHeight);
|
||||
}
|
||||
|
||||
private void animateOut() {
|
||||
animate(0.0);
|
||||
}
|
||||
|
||||
private Timeline timeline;
|
||||
|
||||
protected void animate(Number target) {
|
||||
if (timeline != null) {
|
||||
timeline.stop();
|
||||
timeline = null;
|
||||
}
|
||||
Duration duration;
|
||||
Interpolator interpolator;
|
||||
if (target.intValue() > 0) {
|
||||
interpolator = new ElasticInterpolator(EasingMode.EASE_OUT, 1, 2);
|
||||
duration = ANIM_IN_DURATION;
|
||||
}
|
||||
else {
|
||||
interpolator = Interpolator.EASE_OUT;
|
||||
duration = ANIM_OUT_DURATION;
|
||||
}
|
||||
KeyFrame kf = new KeyFrame(duration, new KeyValue(bar.prefHeightProperty(), target, interpolator));
|
||||
timeline = new Timeline(kf);
|
||||
timeline.setOnFinished(x -> timeline = null);
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
public Item pushItem(String string, @Nullable ObservableDoubleValue progress) {
|
||||
Item i = new Item(string, progress);
|
||||
items.add(i);
|
||||
return i;
|
||||
}
|
||||
}
|
166
src/main/java/wallettemplate/utils/GuiUtils.java
Normal file
166
src/main/java/wallettemplate/utils/GuiUtils.java
Normal file
@ -0,0 +1,166 @@
|
||||
package wallettemplate.utils;
|
||||
|
||||
import javafx.animation.Animation;
|
||||
import javafx.animation.FadeTransition;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
import javafx.animation.ScaleTransition;
|
||||
import javafx.animation.Timeline;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.*;
|
||||
import javafx.scene.effect.*;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
public class GuiUtils {
|
||||
/*public static void runAlert(BiConsumer<Stage, AlertWindowController> setup) {
|
||||
try {
|
||||
// JavaFX2 doesn't actually have a standard alert template. Instead the Scene Builder app will create FXML
|
||||
// files for an alert window for you, and then you customise it as you see fit. I guess it makes sense in
|
||||
// an odd sort of way.
|
||||
Stage dialogStage = new Stage();
|
||||
dialogStage.initModality(Modality.APPLICATION_MODAL);
|
||||
FXMLLoader loader = new FXMLLoader(GuiUtils.class.getResource("alert.fxml"));
|
||||
Pane pane = loader.load();
|
||||
AlertWindowController controller = loader.getController();
|
||||
setup.accept(dialogStage, controller);
|
||||
dialogStage.setScene(new Scene(pane));
|
||||
dialogStage.showAndWait();
|
||||
} catch (IOException e) {
|
||||
// We crashed whilst trying to show the alert dialog (this should never happen). Give up!
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}*/
|
||||
|
||||
/* public static void crashAlert(Throwable t) {
|
||||
t.printStackTrace();
|
||||
Throwable rootCause = Throwables.getRootCause(t);
|
||||
Runnable r = () -> {
|
||||
runAlert((stage, controller) -> controller.crashAlert(stage, rootCause.toString()));
|
||||
Platform.exit();
|
||||
};
|
||||
if (Platform.isFxApplicationThread())
|
||||
r.run();
|
||||
else
|
||||
Platform.runLater(r);
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Show a GUI alert box for any unhandled exceptions that propagate out of this thread.
|
||||
*/
|
||||
/*public static void handleCrashesOnThisThread() {
|
||||
Thread.currentThread().setUncaughtExceptionHandler((thread, exception) -> {
|
||||
GuiUtils.crashAlert(Throwables.getRootCause(exception));
|
||||
});
|
||||
}
|
||||
|
||||
public static void informationalAlert(String message, String details, Object... args) {
|
||||
String formattedDetails = String.format(details, args);
|
||||
Runnable r = () -> runAlert((stage, controller) -> controller.informational(stage, message, formattedDetails));
|
||||
if (Platform.isFxApplicationThread())
|
||||
r.run();
|
||||
else
|
||||
Platform.runLater(r);
|
||||
}*/
|
||||
|
||||
public static final int UI_ANIMATION_TIME_MSEC = 600;
|
||||
public static final Duration UI_ANIMATION_TIME = Duration.millis(UI_ANIMATION_TIME_MSEC);
|
||||
|
||||
public static Animation fadeIn(Node ui) {
|
||||
return fadeIn(ui, 0);
|
||||
}
|
||||
|
||||
public static Animation fadeIn(Node ui, int delayMillis) {
|
||||
ui.setCache(true);
|
||||
FadeTransition ft = new FadeTransition(Duration.millis(UI_ANIMATION_TIME_MSEC), ui);
|
||||
ft.setFromValue(0.0);
|
||||
ft.setToValue(1.0);
|
||||
ft.setOnFinished(ev -> ui.setCache(false));
|
||||
ft.setDelay(Duration.millis(delayMillis));
|
||||
ft.play();
|
||||
return ft;
|
||||
}
|
||||
|
||||
public static Animation fadeOut(Node ui) {
|
||||
FadeTransition ft = new FadeTransition(Duration.millis(UI_ANIMATION_TIME_MSEC), ui);
|
||||
ft.setFromValue(ui.getOpacity());
|
||||
ft.setToValue(0.0);
|
||||
ft.play();
|
||||
return ft;
|
||||
}
|
||||
|
||||
public static Animation fadeOutAndRemove(Pane parentPane, Node... nodes) {
|
||||
Animation animation = fadeOut(nodes[0]);
|
||||
animation.setOnFinished(actionEvent -> parentPane.getChildren().removeAll(nodes));
|
||||
return animation;
|
||||
}
|
||||
|
||||
public static Animation fadeOutAndRemove(Duration duration, Pane parentPane, Node... nodes) {
|
||||
nodes[0].setCache(true);
|
||||
FadeTransition ft = new FadeTransition(duration, nodes[0]);
|
||||
ft.setFromValue(nodes[0].getOpacity());
|
||||
ft.setToValue(0.0);
|
||||
ft.setOnFinished(actionEvent -> parentPane.getChildren().removeAll(nodes));
|
||||
ft.play();
|
||||
return ft;
|
||||
}
|
||||
|
||||
public static void blurOut(Node node) {
|
||||
GaussianBlur blur = new GaussianBlur(0.0);
|
||||
node.setEffect(blur);
|
||||
Timeline timeline = new Timeline();
|
||||
KeyValue kv = new KeyValue(blur.radiusProperty(), 10.0);
|
||||
KeyFrame kf = new KeyFrame(Duration.millis(UI_ANIMATION_TIME_MSEC), kv);
|
||||
timeline.getKeyFrames().add(kf);
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
public static void blurIn(Node node) {
|
||||
GaussianBlur blur = (GaussianBlur) node.getEffect();
|
||||
Timeline timeline = new Timeline();
|
||||
KeyValue kv = new KeyValue(blur.radiusProperty(), 0.0);
|
||||
KeyFrame kf = new KeyFrame(Duration.millis(UI_ANIMATION_TIME_MSEC), kv);
|
||||
timeline.getKeyFrames().add(kf);
|
||||
timeline.setOnFinished(actionEvent -> node.setEffect(null));
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
public static ScaleTransition zoomIn(Node node) {
|
||||
return zoomIn(node, 0);
|
||||
}
|
||||
|
||||
public static ScaleTransition zoomIn(Node node, int delayMillis) {
|
||||
return scaleFromTo(node, 0.95, 1.0, delayMillis);
|
||||
}
|
||||
|
||||
public static ScaleTransition explodeOut(Node node) {
|
||||
return scaleFromTo(node, 1.0, 1.05, 0);
|
||||
}
|
||||
|
||||
private static ScaleTransition scaleFromTo(Node node, double from, double to, int delayMillis) {
|
||||
ScaleTransition scale = new ScaleTransition(Duration.millis(UI_ANIMATION_TIME_MSEC / 2), node);
|
||||
scale.setFromX(from);
|
||||
scale.setFromY(from);
|
||||
scale.setToX(to);
|
||||
scale.setToY(to);
|
||||
scale.setDelay(Duration.millis(delayMillis));
|
||||
scale.play();
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* A useful helper for development purposes. Used as a switch for loading files from local disk, allowing live
|
||||
* editing whilst the app runs without rebuilds.
|
||||
*/
|
||||
/* public static URL getResource(String name) {
|
||||
if (false)
|
||||
return unchecked(() -> new URL("file:///your/path/here/src/main/wallettemplate/" + name));
|
||||
else
|
||||
return MainController.class.getResource(name);
|
||||
}*/
|
||||
public static void checkGuiThread() {
|
||||
checkState(Platform.isFxApplicationThread());
|
||||
}
|
||||
}
|
87
src/main/java/wallettemplate/utils/WTUtils.java
Normal file
87
src/main/java/wallettemplate/utils/WTUtils.java
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 wallettemplate.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Some generic utilities to make Java a bit less annoying.
|
||||
*/
|
||||
public class WTUtils {
|
||||
private static final Logger log = LoggerFactory.getLogger(WTUtils.class);
|
||||
|
||||
public interface UncheckedRun<T> {
|
||||
public T run() throws Throwable;
|
||||
}
|
||||
|
||||
public interface UncheckedRunnable {
|
||||
public void run() throws Throwable;
|
||||
}
|
||||
|
||||
public static <T> T unchecked(UncheckedRun<T> run) {
|
||||
try {
|
||||
return run.run();
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void uncheck(UncheckedRunnable run) {
|
||||
try {
|
||||
run.run();
|
||||
} catch (Throwable throwable) {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ignoreAndLog(UncheckedRunnable runnable) {
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (Throwable t) {
|
||||
log.error("Ignoring error", t);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T ignoredAndLogged(UncheckedRun<T> runnable) {
|
||||
try {
|
||||
return runnable.run();
|
||||
} catch (Throwable t) {
|
||||
log.error("Ignoring error", t);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean didThrow(UncheckedRun run) {
|
||||
try {
|
||||
run.run();
|
||||
return false;
|
||||
} catch (Throwable throwable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean didThrow(UncheckedRunnable run) {
|
||||
try {
|
||||
run.run();
|
||||
return false;
|
||||
} catch (Throwable throwable) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package wallettemplate.utils.easing;
|
||||
|
||||
import javafx.animation.Interpolator;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
|
||||
/**
|
||||
* The abstract base class for all easing interpolators.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
*/
|
||||
public abstract class EasingInterpolator extends Interpolator {
|
||||
|
||||
/**
|
||||
* The easing mode.
|
||||
*/
|
||||
private ObjectProperty<EasingMode> easingMode = new SimpleObjectProperty<>(EasingMode.EASE_OUT);
|
||||
|
||||
/**
|
||||
* Constructs the interpolator with a specific easing mode.
|
||||
*
|
||||
* @param easingMode The easing mode.
|
||||
*/
|
||||
public EasingInterpolator(EasingMode easingMode) {
|
||||
this.easingMode.set(easingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* The easing mode property.
|
||||
*
|
||||
* @return The property.
|
||||
* @see #getEasingMode()
|
||||
* @see #setEasingMode(EasingMode)
|
||||
*/
|
||||
public ObjectProperty<EasingMode> easingModeProperty() {
|
||||
return easingMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the easing mode.
|
||||
*
|
||||
* @return The easing mode.
|
||||
* @see #easingModeProperty()
|
||||
*/
|
||||
public EasingMode getEasingMode() {
|
||||
return easingMode.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the easing mode.
|
||||
*
|
||||
* @param easingMode The easing mode.
|
||||
* @see #easingModeProperty()
|
||||
*/
|
||||
public void setEasingMode(EasingMode easingMode) {
|
||||
this.easingMode.set(easingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the base curve for the interpolator.
|
||||
* The base curve is then transformed into an easing-in, easing-out easing-both curve.
|
||||
*
|
||||
* @param v The normalized value/time/progress of the interpolation (between 0 and 1).
|
||||
* @return The resulting value of the function, should return a value between 0 and 1.
|
||||
* @see javafx.animation.Interpolator#curve(double)
|
||||
*/
|
||||
protected abstract double baseCurve(final double v);
|
||||
|
||||
/**
|
||||
* Curves the function depending on the easing mode.
|
||||
*
|
||||
* @param v The normalized value (between 0 and 1).
|
||||
* @return The resulting value of the function.
|
||||
*/
|
||||
@Override
|
||||
protected final double curve(final double v) {
|
||||
switch (easingMode.get()) {
|
||||
case EASE_IN:
|
||||
return baseCurve(v);
|
||||
case EASE_OUT:
|
||||
return 1 - baseCurve(1 - v);
|
||||
case EASE_BOTH:
|
||||
if (v <= 0.5) {
|
||||
return baseCurve(2 * v) / 2;
|
||||
}
|
||||
else {
|
||||
return (2 - baseCurve(2 * (1 - v))) / 2;
|
||||
}
|
||||
|
||||
}
|
||||
return baseCurve(v);
|
||||
}
|
||||
}
|
12
src/main/java/wallettemplate/utils/easing/EasingMode.java
Normal file
12
src/main/java/wallettemplate/utils/easing/EasingMode.java
Normal file
@ -0,0 +1,12 @@
|
||||
package wallettemplate.utils.easing;
|
||||
|
||||
/**
|
||||
* Defines the three easing modes, ease-in, ease-out and ease-both.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
*/
|
||||
public enum EasingMode {
|
||||
EASE_IN,
|
||||
EASE_OUT,
|
||||
EASE_BOTH
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, Christian Schudt
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
package wallettemplate.utils.easing;
|
||||
|
||||
import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
|
||||
/**
|
||||
* This interpolator simulates an elastic behavior.
|
||||
* <p/>
|
||||
* The following curve illustrates the interpolation.
|
||||
* </p>
|
||||
* <svg style="width:300px;" xmlns="http://www.w3.org/2000/svg" viewBox="-2 -40 124 140">
|
||||
* <line style="stroke: rgb(187, 187, 187); stroke-width: 1px;" y2="60" y1="0" x2="0" x1="0"/>
|
||||
* <text style="font-size: 12px; fill: rgb(187, 187, 187);" y="6" x="2">x</text>
|
||||
* <line style="stroke: rgb(187, 187, 187); stroke-width: 1px;" y2="60" y1="60" x2="120" x1="0"/>
|
||||
* <text style="font-size: 12px; fill: rgb(187, 187, 187);" y="57" x="115">t</text>
|
||||
* <path style="fill: rgba(255, 255, 255, 0);stroke: black;stroke-width: 2px;"
|
||||
* d="M0,60 L1.2,54.8 2.4,47.7 3.6,39.4 4.8,30.4 6.0,21.2 7.2,12.2 8.4,3.9 9.6,-3.6 10.8,-9.9 12.0,-15.0 13.2,
|
||||
* -18.7 14.4,-21.1 15.6,-22.3 16.8,-22.2 18.0,-21.2 19.2,-19.4 20.4,-16.9 21.6,-13.9 22.8,-10.8 24.0,-7.5 25.2,
|
||||
* -4.3 26.4,-1.4 27.6,1.3 28.8,3.5 30.0,5.3 31.2,6.6 32.4,7.5 33.6,7.9 34.8,7.9 36.0,7.5 37.2,6.8 38.4,6.0 39.6,
|
||||
* 4.9 40.8,3.8 42.0,2.7 43.2,1.5 44.4,0.5 45.6,-0.5 46.8,-1.2 48.0,-1.9 49.2,-2.3 50.4,-2.6 51.6,-2.8 52.8,
|
||||
* -2.8 54.0,-2.7 55.2,-2.4 56.4,-2.1 57.6,-1.7 58.8,-1.3 60.0,-0.9 61.2,-0.5 62.4,-0.2 63.6,0.2 64.8,0.4 66.0,
|
||||
* 0.7 67.2,0.8 68.4,0.9 69.6,1.0 70.8,1.0 72.0,0.9 73.2,0.9 74.4,0.7 75.6,0.6 76.8,0.5 78.0,0.3 79.2,0.2 80.4,
|
||||
* 0.1 81.6,-0.1 82.8,-0.2 84.0,-0.2 85.2,-0.3 86.4,-0.3 87.6,-0.3 88.8,-0.3 90.0,-0.3 91.2,-0.3 92.4,-0.3 93.6,
|
||||
* -0.2 94.8,-0.2 96.0,-0.1 97.2,-0.1 98.4,-0.0 99.6,0.0 100.8,0.1 102.0,0.1 103.2,0.1 104.4,0.1 105.6,0.1 106.8,
|
||||
* 0.1 108.0,0.1 109.2,0.1 110.4,0.1 111.6,0.1 112.8,0.1 114.0,0.0 115.2,0.0 116.4,0.0 117.6,-0.0 118.8,-0.0 120.0,
|
||||
* 0.0"/>
|
||||
* </svg>
|
||||
* <p>
|
||||
* The math in this class is taken from
|
||||
* <a href="http://www.robertpenner.com/easing/">http://www.robertpenner.com/easing/</a>.
|
||||
*
|
||||
* @author Christian Schudt
|
||||
*/
|
||||
public class ElasticInterpolator extends EasingInterpolator {
|
||||
|
||||
/**
|
||||
* The amplitude.
|
||||
*/
|
||||
private DoubleProperty amplitude = new SimpleDoubleProperty(this, "amplitude", 1);
|
||||
|
||||
/**
|
||||
* The number of oscillations.
|
||||
*/
|
||||
private DoubleProperty oscillations = new SimpleDoubleProperty(this, "oscillations", 3);
|
||||
|
||||
/**
|
||||
* Default constructor. Initializes the interpolator with ease out mode.
|
||||
*/
|
||||
public ElasticInterpolator() {
|
||||
this(EasingMode.EASE_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the interpolator with a specific easing mode.
|
||||
*
|
||||
* @param easingMode The easing mode.
|
||||
*/
|
||||
public ElasticInterpolator(EasingMode easingMode) {
|
||||
super(easingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the easing mode.
|
||||
*
|
||||
* @param easingMode The easing mode.
|
||||
* @see #easingModeProperty()
|
||||
*/
|
||||
public ElasticInterpolator(EasingMode easingMode, double amplitude, double oscillations) {
|
||||
super(easingMode);
|
||||
this.amplitude.set(amplitude);
|
||||
this.oscillations.set(oscillations);
|
||||
}
|
||||
|
||||
/**
|
||||
* The oscillations property. Defines number of oscillations.
|
||||
*
|
||||
* @return The property.
|
||||
* @see #getOscillations()
|
||||
* @see #setOscillations(double)
|
||||
*/
|
||||
public DoubleProperty oscillationsProperty() {
|
||||
return oscillations;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amplitude. The minimum value is 1. If this value is < 1 it will be set to 1 during animation.
|
||||
*
|
||||
* @return The property.
|
||||
* @see #getAmplitude()
|
||||
* @see #setAmplitude(double)
|
||||
*/
|
||||
public DoubleProperty amplitudeProperty() {
|
||||
return amplitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amplitude.
|
||||
*
|
||||
* @return The amplitude.
|
||||
* @see #amplitudeProperty()
|
||||
*/
|
||||
public double getAmplitude() {
|
||||
return amplitude.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amplitude.
|
||||
*
|
||||
* @param amplitude The amplitude.
|
||||
* @see #amplitudeProperty()
|
||||
*/
|
||||
public void setAmplitude(final double amplitude) {
|
||||
this.amplitude.set(amplitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of oscillations.
|
||||
*
|
||||
* @return The oscillations.
|
||||
* @see #oscillationsProperty()
|
||||
*/
|
||||
public double getOscillations() {
|
||||
return oscillations.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of oscillations.
|
||||
*
|
||||
* @param oscillations The oscillations.
|
||||
* @see #oscillationsProperty()
|
||||
*/
|
||||
public void setOscillations(final double oscillations) {
|
||||
this.oscillations.set(oscillations);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double baseCurve(double v) {
|
||||
if (v == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (v == 1) {
|
||||
return 1;
|
||||
}
|
||||
double p = 1.0 / oscillations.get();
|
||||
double a = amplitude.get();
|
||||
double s;
|
||||
if (a < Math.abs(1)) {
|
||||
a = 1;
|
||||
s = p / 4;
|
||||
}
|
||||
else {
|
||||
s = p / (2 * Math.PI) * Math.asin(1 / a);
|
||||
}
|
||||
return -(a * Math.pow(2, 10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / p));
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@
|
||||
|
||||
<logger name="io.bitsquare" level="TRACE"/>
|
||||
|
||||
<logger name="org.bitcoinj" level="WARN"/>
|
||||
<logger name="org.bitcoinj" level="DEBUG"/>
|
||||
<logger name="net.tomp2p" level="WARN"/>
|
||||
|
||||
<logger name="io.netty.util" level="WARN"/>
|
||||
@ -36,6 +36,10 @@
|
||||
<logger name="io.bitsquare.gui.CachedViewController" level="OFF"/>
|
||||
<logger name="io.bitsquare.gui.util.Profiler" level="TRACE"/>
|
||||
|
||||
|
||||
<logger name=" org.bitcoinj.core.BitcoinSerializer" level="WARN"/>
|
||||
<logger name=" org.bitcoinj.core.AbstractBlockChain" level="WARN"/>
|
||||
|
||||
<!--
|
||||
<logger name="org.bitcoinj.core.Wallet" level="OFF"/>
|
||||
<logger name="org.bitcoinj.core.MemoryPool" level="OFF"/>
|
||||
|
BIN
src/main/resources/wallet/checkpoints.testnet
Normal file
BIN
src/main/resources/wallet/checkpoints.testnet
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user