mirror of
https://github.com/haveno-dex/haveno.git
synced 2025-04-20 23:56:30 -04:00
Fix duplicate popup displays
This commit is contained in:
parent
7612e53271
commit
f706ddaad4
@ -333,7 +333,7 @@ public class TradeManager {
|
||||
}
|
||||
|
||||
// If trade was completed (closed without fault but might be closed by a dispute) we move it to the closed trades
|
||||
private void addTradeToClosedTrades(Trade trade) {
|
||||
public void addTradeToClosedTrades(Trade trade) {
|
||||
trades.remove(trade);
|
||||
closedTradableManager.add(trade);
|
||||
}
|
||||
|
@ -983,7 +983,7 @@ textfield */
|
||||
-fx-background-color: linear-gradient(to bottom, #fcfcfc, #e5e5e5);
|
||||
-fx-background-radius: 5 5 5 5;
|
||||
-fx-background-insets: 5 5 20 20;
|
||||
-fx-effect: dropshadow(gaussian, #666, 10, 0, 2, 2);
|
||||
-fx-effect: dropshadow(gaussian, #333, 12, 0, -1, 3);
|
||||
}
|
||||
|
||||
.popup-icon-information {
|
||||
|
@ -109,7 +109,7 @@ public class AddressTextField extends AnchorPane {
|
||||
PopOver popOver = new PopOver(pane);
|
||||
popOver.setDetachedTitle("Scan QR code for this address");
|
||||
popOver.setDetached(true);
|
||||
popOver.setOnHiding(windowEvent -> MainView.removeBlur());
|
||||
popOver.setOnHiding(windowEvent -> MainView.removeEffect());
|
||||
|
||||
Window window = getScene().getWindow();
|
||||
double x = Math.round(window.getX() + (window.getWidth() - 320) / 2);
|
||||
|
@ -67,15 +67,19 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
|
||||
}
|
||||
|
||||
public static void blurLight() {
|
||||
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, true, false, 5);
|
||||
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, -0.1, false, 5);
|
||||
}
|
||||
|
||||
public static void blurUltraLight() {
|
||||
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, true, false, 2);
|
||||
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, -0.1, false, 2);
|
||||
}
|
||||
|
||||
public static void removeBlur() {
|
||||
transitions.removeBlur(MainView.rootContainer);
|
||||
public static void darken() {
|
||||
transitions.darken(MainView.rootContainer, Transitions.DEFAULT_DURATION, false);
|
||||
}
|
||||
|
||||
public static void removeEffect() {
|
||||
transitions.removeEffect(MainView.rootContainer);
|
||||
}
|
||||
|
||||
private final ToggleGroup navButtons = new ToggleGroup();
|
||||
|
@ -138,11 +138,11 @@ public class AltCoinAccountsView extends ActivatableViewAndModel<GridPane, AltCo
|
||||
private void onDeleteAccount(PaymentAccount paymentAccount) {
|
||||
new Popup().warning("Do you really want to delete the selected account?")
|
||||
.actionButtonText("Yes")
|
||||
.closeButtonText("Cancel")
|
||||
.onAction(() -> {
|
||||
model.onDeleteAccount(paymentAccount);
|
||||
removeSelectAccountForm();
|
||||
})
|
||||
.closeButtonText("Cancel")
|
||||
.show();
|
||||
}
|
||||
|
||||
|
@ -140,11 +140,11 @@ public class FiatAccountsView extends ActivatableViewAndModel<GridPane, FiatAcco
|
||||
private void onDeleteAccount(PaymentAccount paymentAccount) {
|
||||
new Popup().warning("Do you really want to delete the selected account?")
|
||||
.actionButtonText("Yes")
|
||||
.closeButtonText("Cancel")
|
||||
.onAction(() -> {
|
||||
model.onDeleteAccount(paymentAccount);
|
||||
removeSelectAccountForm();
|
||||
})
|
||||
.closeButtonText("Cancel")
|
||||
.show();
|
||||
}
|
||||
|
||||
|
@ -113,12 +113,12 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
|
||||
if (preferences.showAgain(key)) {
|
||||
new Popup().warning("You have not setup a wallet password which would protect the display of the seed words.\n\n" +
|
||||
"Do you want to display the seed words?")
|
||||
.closeButtonText("Yes, and don't ask me again")
|
||||
.onClose(() -> {
|
||||
.actionButtonText("Yes, and don't ask me again")
|
||||
.onAction(() -> {
|
||||
preferences.dontShowAgain(key, true);
|
||||
showSeedScreen(keyChainSeed);
|
||||
})
|
||||
.actionButtonText("No")
|
||||
.closeButtonText("No")
|
||||
.show();
|
||||
} else {
|
||||
showSeedScreen(keyChainSeed);
|
||||
|
@ -136,11 +136,8 @@ public class DisputesView extends ActivatableViewAndModel<TabPane, Activatable>
|
||||
"at the Bitsquare.io web page.\n\n" +
|
||||
"If you are sure you want to open a support ticket please select the trade which causes the problem " +
|
||||
"under \"Portfolio/Open trades\" and type the key combination \"cmd + o\" to open the support ticket.")
|
||||
.closeButtonText("Go to \"Open trades\"")
|
||||
.onClose(() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class))
|
||||
.actionButtonText("Close")
|
||||
.onAction(() -> {
|
||||
})
|
||||
.actionButtonText("Go to \"Open trades\"")
|
||||
.onAction(() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class))
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
}
|
||||
|
@ -92,11 +92,9 @@ public class FundsView extends ActivatableViewAndModel<TabPane, Activatable> {
|
||||
"Withdrawing funds can be done after a trade is completed.\n\n" +
|
||||
"Dedicated wallets help protect user privacy and prevent leaking information of previous trades to other" +
|
||||
"traders.")
|
||||
.closeButtonText("I want to learn more")
|
||||
.onClose(() -> Utilities.openWebPage("https://bitsquare.io/faq"))
|
||||
.actionButtonText("I understand")
|
||||
.onAction(() -> {
|
||||
})
|
||||
.closeButtonText("I understand")
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> Utilities.openWebPage("https://bitsquare.io/faq"))
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
}
|
||||
|
@ -139,8 +139,8 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
||||
xAxis.setTickLabelFormatter(new NumberAxis.DefaultFormatter(xAxis, "", ""));
|
||||
});
|
||||
|
||||
buyOfferTableView.setItems(model.getBuyOfferList());
|
||||
sellOfferTableView.setItems(model.getSellOfferList());
|
||||
buyOfferTableView.setItems(model.getTop3BuyOfferList());
|
||||
sellOfferTableView.setItems(model.getTop3SellOfferList());
|
||||
|
||||
updateChartData();
|
||||
}
|
||||
@ -155,10 +155,10 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
|
||||
|
||||
private Tuple3<TableView<Offer>, VBox, Button> getOfferTable(Offer.Direction direction) {
|
||||
TableView<Offer> tableView = new TableView<>();
|
||||
tableView.setMinHeight(99);
|
||||
tableView.setMaxHeight(99);
|
||||
tableView.setMinHeight(100);
|
||||
tableView.setMaxHeight(100);
|
||||
tableView.setMinWidth(390);
|
||||
tableView.setMouseTransparent(true);
|
||||
// tableView.setMouseTransparent(true);
|
||||
|
||||
// price
|
||||
TableColumn<Offer, Offer> priceColumn = new TableColumn<>();
|
||||
|
@ -50,8 +50,8 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
||||
private final List<XYChart.Data> sellData = new ArrayList();
|
||||
private final ObservableList<OfferBookListItem> offerBookListItems;
|
||||
private final ListChangeListener<OfferBookListItem> listChangeListener;
|
||||
private final ObservableList<Offer> buyOfferList = FXCollections.observableArrayList();
|
||||
private final ObservableList<Offer> sellOfferList = FXCollections.observableArrayList();
|
||||
private final ObservableList<Offer> top3BuyOfferList = FXCollections.observableArrayList();
|
||||
private final ObservableList<Offer> top3SellOfferList = FXCollections.observableArrayList();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -83,13 +83,8 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
||||
}
|
||||
|
||||
private void updateChartData(ObservableList<OfferBookListItem> offerBookListItems) {
|
||||
List<Offer> offerList = offerBookListItems.stream()
|
||||
List<Offer> allBuyOffers = offerBookListItems.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
buyOfferList.clear();
|
||||
buyOfferList.addAll(offerList
|
||||
.stream()
|
||||
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode())
|
||||
&& e.getDirection().equals(Offer.Direction.BUY))
|
||||
.sorted((o1, o2) -> {
|
||||
@ -99,13 +94,12 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
||||
return a < b ? 1 : -1;
|
||||
return 0;
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
buyOfferList.subList(0, Math.min(3, buyOfferList.size()));
|
||||
iterateBuyOffers(buyOfferList, Offer.Direction.BUY, buyData);
|
||||
.collect(Collectors.toList());
|
||||
top3BuyOfferList.setAll(allBuyOffers.subList(0, Math.min(3, allBuyOffers.size())));
|
||||
buildChartDataItems(allBuyOffers, Offer.Direction.BUY, buyData);
|
||||
|
||||
sellOfferList.clear();
|
||||
sellOfferList.addAll(offerList
|
||||
.stream()
|
||||
List<Offer> allSellOffers = offerBookListItems.stream()
|
||||
.map(OfferBookListItem::getOffer)
|
||||
.filter(e -> e.getCurrencyCode().equals(tradeCurrency.get().getCode())
|
||||
&& e.getDirection().equals(Offer.Direction.SELL))
|
||||
.sorted((o1, o2) -> {
|
||||
@ -115,12 +109,12 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
||||
return a > b ? 1 : -1;
|
||||
return 0;
|
||||
})
|
||||
.collect(Collectors.toList()));
|
||||
sellOfferList.subList(0, Math.min(3, sellOfferList.size()));
|
||||
iterateBuyOffers(sellOfferList, Offer.Direction.SELL, sellData);
|
||||
.collect(Collectors.toList());
|
||||
top3SellOfferList.setAll(allSellOffers.subList(0, Math.min(3, allSellOffers.size())));
|
||||
buildChartDataItems(allSellOffers, Offer.Direction.SELL, sellData);
|
||||
}
|
||||
|
||||
private void iterateBuyOffers(List<Offer> sortedList, Offer.Direction direction, List<XYChart.Data> data) {
|
||||
private void buildChartDataItems(List<Offer> sortedList, Offer.Direction direction, List<XYChart.Data> data) {
|
||||
data.clear();
|
||||
double accumulatedAmount = 0;
|
||||
for (Offer offer : sortedList) {
|
||||
@ -165,12 +159,12 @@ class MarketsChartsViewModel extends ActivatableViewModel {
|
||||
return offerBookListItems;
|
||||
}
|
||||
|
||||
public ObservableList<Offer> getBuyOfferList() {
|
||||
return buyOfferList;
|
||||
public ObservableList<Offer> getTop3BuyOfferList() {
|
||||
return top3BuyOfferList;
|
||||
}
|
||||
|
||||
public ObservableList<Offer> getSellOfferList() {
|
||||
return sellOfferList;
|
||||
public ObservableList<Offer> getTop3SellOfferList() {
|
||||
return top3SellOfferList;
|
||||
}
|
||||
|
||||
public ObservableList<TradeCurrency> getTradeCurrencies() {
|
||||
|
@ -208,7 +208,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
public void onClose() {
|
||||
// we use model.placeOfferCompleted to not react on close which was triggered by a successful placeOffer
|
||||
if (model.dataModel.isWalletFunded.get() && !model.placeOfferCompleted.get())
|
||||
new Popup().warning("You have already funds paid in.\n" +
|
||||
new Popup().information("You have already funds paid in.\n" +
|
||||
"In the \"Funds/Available for withdrawal\" section you can withdraw those funds.").show();
|
||||
}
|
||||
|
||||
@ -262,11 +262,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
new Popup().backgroundInfo("To ensure that both traders follow the trade protocol they need to pay a security deposit.\n\n" +
|
||||
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
||||
"It will be refunded to you after the trade has successfully completed.")
|
||||
.closeButtonText("I want to learn more")
|
||||
.onClose(() -> Utilities.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.actionButtonText("I understand")
|
||||
.onAction(() -> {
|
||||
})
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> Utilities.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.closeButtonText("I understand")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
||||
@ -281,7 +279,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
"(you can copy the address in the screen below after closing that popup)\n\n" +
|
||||
"Make sure you use a sufficiently high mining fee of at least " +
|
||||
model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) +
|
||||
" to avoid problems that your transaction does not get confirmed in the blockchain.\n\n" +
|
||||
" to avoid problems that your transaction does not get confirmed in the blockchain.\n" +
|
||||
"Transactions with a lower fee will not be accepted.\n\n" +
|
||||
"You can see the status of your incoming payment and all the details in the screen below.")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
@ -731,7 +730,17 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
|
||||
spinnerInfoLabel = placeOfferTuple.third;
|
||||
|
||||
cancelButton2 = addButton(gridPane, ++gridRow, BSResources.get("shared.cancel"));
|
||||
cancelButton2.setOnAction(e -> close());
|
||||
cancelButton2.setOnAction(e -> {
|
||||
if (model.dataModel.isWalletFunded.get())
|
||||
new Popup().warning("You have already paid in the funds.\n" +
|
||||
"Are you sure you want to cancel.")
|
||||
.actionButtonText("No")
|
||||
.closeButtonText("Yes, close")
|
||||
.onClose(() -> close())
|
||||
.show();
|
||||
else
|
||||
close();
|
||||
});
|
||||
cancelButton2.setDefaultButton(false);
|
||||
cancelButton2.setVisible(false);
|
||||
cancelButton2.setId("cancel-button");
|
||||
|
@ -29,7 +29,6 @@ import io.bitsquare.btc.listeners.BalanceListener;
|
||||
import io.bitsquare.btc.pricefeed.PriceFeed;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.gui.common.model.ActivatableDataModel;
|
||||
import io.bitsquare.gui.main.overlays.notifications.Notification;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.overlays.windows.WalletPasswordWindow;
|
||||
import io.bitsquare.gui.util.BSFormatter;
|
||||
@ -91,7 +90,6 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||
private BalanceListener balanceListener;
|
||||
private PaymentAccount paymentAccount;
|
||||
private boolean isTabSelected;
|
||||
private Notification walletFundedNotification;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -214,6 +212,7 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||
priceFeed.setCurrencyCode(offer.getCurrencyCode());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// UI actions
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -325,17 +324,8 @@ class TakeOfferDataModel extends ActivatableDataModel {
|
||||
private void updateBalance(@NotNull Coin balance) {
|
||||
isWalletFunded.set(totalToPayAsCoin.get() != null && balance.compareTo(totalToPayAsCoin.get()) >= 0);
|
||||
|
||||
if (isWalletFunded.get()) {
|
||||
if (isWalletFunded.get())
|
||||
walletService.removeBalanceListener(balanceListener);
|
||||
if (walletFundedNotification == null) {
|
||||
walletFundedNotification = new Notification()
|
||||
.headLine("Trading wallet update")
|
||||
.notification("Your trading wallet is sufficiently funded.\n" +
|
||||
"Amount: " + formatter.formatCoinWithCode(totalToPayAsCoin.get()))
|
||||
.autoClose();
|
||||
walletFundedNotification.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isMinAmountLessOrEqualAmount() {
|
||||
|
@ -36,6 +36,7 @@ import io.bitsquare.gui.main.account.settings.AccountSettingsView;
|
||||
import io.bitsquare.gui.main.funds.FundsView;
|
||||
import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView;
|
||||
import io.bitsquare.gui.main.offer.OfferView;
|
||||
import io.bitsquare.gui.main.overlays.notifications.Notification;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow;
|
||||
import io.bitsquare.gui.main.portfolio.PortfolioView;
|
||||
@ -103,6 +104,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
private SimpleBooleanProperty errorPopupDisplayed;
|
||||
private ChangeListener<Coin> feeFromFundingTxListener;
|
||||
private boolean offerDetailsWindowDisplayed;
|
||||
private Notification walletFundedNotification;
|
||||
private Subscription isWalletFundedSubscription;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -308,6 +311,9 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
|
||||
if (spinner != null)
|
||||
spinner.setProgress(0);
|
||||
|
||||
if (isWalletFundedSubscription != null)
|
||||
isWalletFundedSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
|
||||
@ -411,11 +417,9 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
new Popup().backgroundInfo("To ensure that both traders follow the trade protocol they need to pay a security deposit.\n\n" +
|
||||
"The deposit will stay in your local trading wallet until the offer gets accepted by another trader.\n" +
|
||||
"It will be refunded to you after the trade has successfully completed.")
|
||||
.closeButtonText("I want to learn more")
|
||||
.onClose(() -> Utilities.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.actionButtonText("I understand")
|
||||
.onAction(() -> {
|
||||
})
|
||||
.actionButtonText("Visit FAQ web page")
|
||||
.onAction(() -> Utilities.openWebPage("https://bitsquare.io/faq#6"))
|
||||
.closeButtonText("I understand")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
|
||||
@ -429,7 +433,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
model.getAddressAsString() + "\n(you can copy the address in the screen below after closing that popup)\n\n" +
|
||||
"Make sure you use a sufficiently high mining fee of at least " +
|
||||
model.formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) +
|
||||
" to avoid problems that your transaction does not get confirmed in the blockchain.\n\n" +
|
||||
" to avoid problems that your transaction does not get confirmed in the blockchain.\n" +
|
||||
"Transactions with a lower fee will not be accepted.\n\n" +
|
||||
"You can see the status of your incoming payment and all the details in the screen below.")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
@ -456,6 +461,30 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
balanceTextField.setVisible(true);
|
||||
|
||||
setupTotalToPayInfoIconLabel();
|
||||
|
||||
if (model.dataModel.isWalletFunded.get()) {
|
||||
if (walletFundedNotification == null) {
|
||||
walletFundedNotification = new Notification()
|
||||
.headLine("Trading wallet update")
|
||||
.notification("Your trading wallet was already sufficiently funded from an earlier take offer attempt.\n" +
|
||||
"Amount: " + formatter.formatCoinWithCode(model.dataModel.totalToPayAsCoin.get()))
|
||||
.autoClose();
|
||||
walletFundedNotification.show();
|
||||
}
|
||||
} else {
|
||||
isWalletFundedSubscription = EasyBind.subscribe(model.dataModel.isWalletFunded, isFunded -> {
|
||||
if (isFunded) {
|
||||
if (walletFundedNotification == null) {
|
||||
walletFundedNotification = new Notification()
|
||||
.headLine("Trading wallet update")
|
||||
.notification("Your trading wallet is sufficiently funded.\n" +
|
||||
"Amount: " + formatter.formatCoinWithCode(model.dataModel.totalToPayAsCoin.get()))
|
||||
.autoClose();
|
||||
walletFundedNotification.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -632,7 +661,17 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
|
||||
spinnerInfoLabel = takeOfferTuple.third;
|
||||
|
||||
cancelButton2 = addButton(gridPane, ++gridRow, BSResources.get("shared.cancel"));
|
||||
cancelButton2.setOnAction(e -> close());
|
||||
cancelButton2.setOnAction(e -> {
|
||||
if (model.dataModel.isWalletFunded.get())
|
||||
new Popup().warning("You have already paid in the funds.\n" +
|
||||
"Are you sure you want to cancel.")
|
||||
.actionButtonText("Yes, cancel")
|
||||
.onAction(() -> close())
|
||||
.closeButtonText("No")
|
||||
.show();
|
||||
else
|
||||
close();
|
||||
});
|
||||
cancelButton2.setDefaultButton(false);
|
||||
cancelButton2.setVisible(false);
|
||||
cancelButton2.setId("cancel-button");
|
||||
|
@ -17,7 +17,6 @@
|
||||
|
||||
package io.bitsquare.gui.main.overlays;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
import io.bitsquare.common.Timer;
|
||||
import io.bitsquare.common.UserThread;
|
||||
import io.bitsquare.common.util.Utilities;
|
||||
@ -34,10 +33,14 @@ import javafx.collections.ObservableList;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.scene.Camera;
|
||||
import javafx.scene.PerspectiveCamera;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.transform.Rotate;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.stage.StageStyle;
|
||||
@ -55,6 +58,50 @@ import static io.bitsquare.gui.util.FormBuilder.addCheckBox;
|
||||
public abstract class Overlay<T extends Overlay> {
|
||||
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Enum
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private enum AnimationType {
|
||||
FadeInAtCenter,
|
||||
SlideDownFromCenterTop,
|
||||
SlideFromRightTop,
|
||||
ScaleDownToCenter,
|
||||
ScaleFromCenter,
|
||||
ScaleYFromCenter
|
||||
}
|
||||
|
||||
private enum ChangeBackgroundType {
|
||||
BlurLight,
|
||||
BlurUltraLight,
|
||||
Darken
|
||||
}
|
||||
|
||||
protected enum Type {
|
||||
Undefined(AnimationType.ScaleFromCenter, ChangeBackgroundType.BlurLight),
|
||||
|
||||
Notification(AnimationType.SlideFromRightTop, ChangeBackgroundType.BlurLight),
|
||||
|
||||
BackgroundInfo(AnimationType.SlideDownFromCenterTop, ChangeBackgroundType.BlurUltraLight),
|
||||
Feedback(AnimationType.SlideDownFromCenterTop, ChangeBackgroundType.Darken),
|
||||
|
||||
Information(AnimationType.FadeInAtCenter, ChangeBackgroundType.BlurLight),
|
||||
Instruction(AnimationType.ScaleFromCenter, ChangeBackgroundType.BlurLight),
|
||||
Attention(AnimationType.ScaleFromCenter, ChangeBackgroundType.BlurLight),
|
||||
Confirmation(AnimationType.ScaleYFromCenter, ChangeBackgroundType.BlurLight),
|
||||
|
||||
Warning(AnimationType.ScaleDownToCenter, ChangeBackgroundType.BlurLight),
|
||||
Error(AnimationType.ScaleDownToCenter, ChangeBackgroundType.BlurLight);
|
||||
|
||||
public AnimationType animationType;
|
||||
public ChangeBackgroundType changeBackgroundType;
|
||||
|
||||
Type(AnimationType animationType, ChangeBackgroundType changeBackgroundType) {
|
||||
this.animationType = animationType;
|
||||
this.changeBackgroundType = changeBackgroundType;
|
||||
}
|
||||
}
|
||||
|
||||
protected final static double DEFAULT_WIDTH = 600;
|
||||
protected int rowIndex = -1;
|
||||
protected String headLine;
|
||||
@ -81,8 +128,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
protected ChangeListener<Number> positionListener;
|
||||
protected Timer centerTime;
|
||||
protected double buttonDistance = 20;
|
||||
private String type;
|
||||
private AwesomeIcon awesomeIcon;
|
||||
protected Type type = Type.Undefined;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -163,7 +209,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T notification(String message) {
|
||||
type = "notification";
|
||||
type = Type.Notification;
|
||||
if (headLine == null)
|
||||
this.headLine = "Notification";
|
||||
this.message = message;
|
||||
@ -172,7 +218,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T instruction(String message) {
|
||||
type = "instruction";
|
||||
type = Type.Instruction;
|
||||
if (headLine == null)
|
||||
this.headLine = "Instruction";
|
||||
this.message = message;
|
||||
@ -181,7 +227,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T backgroundInfo(String message) {
|
||||
type = "backgroundInfo";
|
||||
type = Type.BackgroundInfo;
|
||||
if (headLine == null)
|
||||
this.headLine = "Background information";
|
||||
this.message = message;
|
||||
@ -190,7 +236,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T feedback(String message) {
|
||||
type = "feedback";
|
||||
type = Type.Feedback;
|
||||
if (headLine == null)
|
||||
this.headLine = "Feedback";
|
||||
this.message = message;
|
||||
@ -199,7 +245,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T confirmation(String message) {
|
||||
type = "confirmation";
|
||||
type = Type.Confirmation;
|
||||
if (headLine == null)
|
||||
this.headLine = "Confirmation";
|
||||
this.message = message;
|
||||
@ -208,7 +254,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T information(String message) {
|
||||
type = "information";
|
||||
type = Type.Information;
|
||||
if (headLine == null)
|
||||
this.headLine = "Information";
|
||||
this.message = message;
|
||||
@ -217,8 +263,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T warning(String message) {
|
||||
type = "warning";
|
||||
awesomeIcon = AwesomeIcon.LIGHTBULB;
|
||||
type = Type.Warning;
|
||||
|
||||
if (headLine == null)
|
||||
this.headLine = "Warning";
|
||||
@ -228,7 +273,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
|
||||
public T error(String message) {
|
||||
type = "error";
|
||||
type = Type.Error;
|
||||
showReportErrorButtons();
|
||||
if (headLine == null)
|
||||
this.headLine = "Error";
|
||||
@ -279,6 +324,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -308,10 +354,18 @@ public abstract class Overlay<T extends Overlay> {
|
||||
|
||||
Scene rootScene = owner.getScene();
|
||||
if (rootScene != null) {
|
||||
stage = new Stage();
|
||||
Scene scene = new Scene(gridPane);
|
||||
scene.getStylesheets().setAll(rootScene.getStylesheets());
|
||||
scene.setFill(Color.TRANSPARENT);
|
||||
|
||||
scene.setOnKeyPressed(e -> {
|
||||
if (e.getCode() == KeyCode.ESCAPE || e.getCode() == KeyCode.ENTER) {
|
||||
e.consume();
|
||||
doClose();
|
||||
}
|
||||
});
|
||||
|
||||
stage = new Stage();
|
||||
stage.setScene(scene);
|
||||
Window window = rootScene.getWindow();
|
||||
setModality();
|
||||
@ -343,183 +397,174 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
}
|
||||
|
||||
protected void animateDisplay() {
|
||||
gridPane.setOpacity(0);
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
double duration = 400;
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop) {
|
||||
double startY = -gridPane.getHeight();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), startY, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), -10, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleFromCenter) {
|
||||
double startScale = 0.25;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleYFromCenter) {
|
||||
double startYScale = 0.25;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startYScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleDownToCenter) {
|
||||
double startScale = 1.1;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.FadeInAtCenter) {
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator)
|
||||
));
|
||||
}
|
||||
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
protected void animateHide(Runnable onFinishedHandler) {
|
||||
if ("backgroundInfo".equals(type))
|
||||
animateToTop(onFinishedHandler);
|
||||
else
|
||||
animateToCenter(onFinishedHandler);
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
double duration = 200;
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop) {
|
||||
double endY = -gridPane.getHeight();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), -10, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), endY, interpolator)
|
||||
));
|
||||
|
||||
timeline.setOnFinished(e -> onFinishedHandler.run());
|
||||
timeline.play();
|
||||
} else if (type.animationType == AnimationType.ScaleFromCenter) {
|
||||
double endScale = 0.25;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), endScale, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleYFromCenter) {
|
||||
gridPane.setRotationAxis(Rotate.X_AXIS);
|
||||
Camera camera = gridPane.getScene().getCamera();
|
||||
gridPane.getScene().setCamera(new PerspectiveCamera());
|
||||
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.rotateProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.rotateProperty(), -90, interpolator),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.ScaleDownToCenter) {
|
||||
double endScale = 0.1;
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), endScale, interpolator)
|
||||
));
|
||||
} else if (type.animationType == AnimationType.FadeInAtCenter) {
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator)
|
||||
));
|
||||
}
|
||||
|
||||
timeline.setOnFinished(e -> onFinishedHandler.run());
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
protected void layout() {
|
||||
if ("backgroundInfo".equals(type))
|
||||
layoutAtTop();
|
||||
else
|
||||
layoutAtCenter();
|
||||
if (owner == null)
|
||||
owner = MainView.getRootContainer();
|
||||
Scene rootScene = owner.getScene();
|
||||
if (rootScene != null) {
|
||||
Window window = rootScene.getWindow();
|
||||
double titleBarHeight = window.getHeight() - rootScene.getHeight();
|
||||
stage.setX(Math.round(window.getX() + (owner.getWidth() - stage.getWidth()) / 2));
|
||||
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop)
|
||||
stage.setY(Math.round(window.getY() + titleBarHeight));
|
||||
else
|
||||
stage.setY(Math.round(window.getY() + titleBarHeight + (owner.getHeight() - stage.getHeight()) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
protected void addEffectToBackground() {
|
||||
if ("backgroundInfo".equals(type))
|
||||
if (type.changeBackgroundType == ChangeBackgroundType.BlurUltraLight)
|
||||
MainView.blurUltraLight();
|
||||
else
|
||||
else if (type.changeBackgroundType == ChangeBackgroundType.BlurLight)
|
||||
MainView.blurLight();
|
||||
|
||||
}
|
||||
|
||||
protected void animateDisplay() {
|
||||
if ("backgroundInfo".equals(type))
|
||||
animateFromTop();
|
||||
else
|
||||
animateFromCenter();
|
||||
MainView.darken();
|
||||
}
|
||||
|
||||
|
||||
protected void applyStyles() {
|
||||
if ("backgroundInfo".equals(type))
|
||||
applyStylesTop();
|
||||
if (type.animationType == AnimationType.SlideDownFromCenterTop)
|
||||
gridPane.setId("popup-bg-top");
|
||||
else
|
||||
applyStylesCenter();
|
||||
}
|
||||
gridPane.setId("popup-bg");
|
||||
|
||||
protected void layoutAtTop() {
|
||||
if (owner == null)
|
||||
owner = MainView.getRootContainer();
|
||||
Scene rootScene = owner.getScene();
|
||||
if (rootScene != null) {
|
||||
Window window = rootScene.getWindow();
|
||||
double titleBarHeight = window.getHeight() - rootScene.getHeight();
|
||||
stage.setX(Math.round(window.getX() + (owner.getWidth() - stage.getWidth()) / 2));
|
||||
stage.setY(Math.round(window.getY() + titleBarHeight /*+ (owner.getHeight() - stage.getHeight()) / 2*/));
|
||||
}
|
||||
}
|
||||
|
||||
protected void layoutAtCenter() {
|
||||
if (owner == null)
|
||||
owner = MainView.getRootContainer();
|
||||
Scene rootScene = owner.getScene();
|
||||
if (rootScene != null) {
|
||||
Window window = rootScene.getWindow();
|
||||
double titleBarHeight = window.getHeight() - rootScene.getHeight();
|
||||
stage.setX(Math.round(window.getX() + (owner.getWidth() - stage.getWidth()) / 2));
|
||||
stage.setY(Math.round(window.getY() + titleBarHeight + (owner.getHeight() - stage.getHeight()) / 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void animateFromTop() {
|
||||
gridPane.setOpacity(0);
|
||||
double startY = -gridPane.getHeight();
|
||||
double duration = 400;
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), startY, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), -10, interpolator)
|
||||
));
|
||||
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
protected void animateFromCenter() {
|
||||
gridPane.setOpacity(0);
|
||||
double startScale = 0.25;
|
||||
double duration = 400;
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
protected void animateFromBottom() {
|
||||
gridPane.setOpacity(0);
|
||||
double startScale = 0.25;
|
||||
double duration = 400;
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), startScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), startScale, interpolator)
|
||||
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
|
||||
protected void animateToTop(Runnable onFinishedHandler) {
|
||||
double endY = -gridPane.getHeight();
|
||||
double duration = 200;
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), -10, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.translateYProperty(), endY, interpolator)
|
||||
));
|
||||
|
||||
timeline.setOnFinished(e -> onFinishedHandler.run());
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
protected void animateToCenter(Runnable onFinishedHandler) {
|
||||
double endScale = 0.25;
|
||||
double duration = 200;
|
||||
Interpolator interpolator = Interpolator.SPLINE(0.25, 0.1, 0.25, 1);
|
||||
|
||||
Timeline timeline = new Timeline();
|
||||
ObservableList<KeyFrame> keyFrames = timeline.getKeyFrames();
|
||||
keyFrames.add(new KeyFrame(Duration.millis(0),
|
||||
new KeyValue(gridPane.opacityProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), 1, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), 1, interpolator)
|
||||
));
|
||||
keyFrames.add(new KeyFrame(Duration.millis(duration),
|
||||
new KeyValue(gridPane.opacityProperty(), 0, interpolator),
|
||||
new KeyValue(gridPane.scaleXProperty(), endScale, interpolator),
|
||||
new KeyValue(gridPane.scaleYProperty(), endScale, interpolator)
|
||||
));
|
||||
|
||||
timeline.setOnFinished(e -> onFinishedHandler.run());
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
|
||||
protected void applyStylesTop() {
|
||||
gridPane.setId("popup-bg-top");
|
||||
if (headLineLabel != null)
|
||||
headLineLabel.setId("popup-headline");
|
||||
}
|
||||
|
||||
protected void applyStylesCenter() {
|
||||
gridPane.setId("popup-bg");
|
||||
if (headLineLabel != null)
|
||||
headLineLabel.setId("popup-headline");
|
||||
}
|
||||
@ -529,9 +574,8 @@ public abstract class Overlay<T extends Overlay> {
|
||||
stage.initModality(Modality.WINDOW_MODAL);
|
||||
}
|
||||
|
||||
|
||||
protected void removeEffectFromBackground() {
|
||||
MainView.removeBlur();
|
||||
MainView.removeEffect();
|
||||
}
|
||||
|
||||
protected void addHeadLine() {
|
||||
@ -641,10 +685,7 @@ public abstract class Overlay<T extends Overlay> {
|
||||
|
||||
protected void addCloseButton() {
|
||||
closeButton = new Button(closeButtonText == null ? "Close" : closeButtonText);
|
||||
closeButton.setOnAction(event -> {
|
||||
hide();
|
||||
closeHandlerOptional.ifPresent(Runnable::run);
|
||||
});
|
||||
closeButton.setOnAction(event -> doClose());
|
||||
|
||||
if (actionHandlerOptional.isPresent() || actionButtonText != null) {
|
||||
actionButton = new Button(actionButtonText == null ? "Ok" : actionButtonText);
|
||||
@ -678,6 +719,11 @@ public abstract class Overlay<T extends Overlay> {
|
||||
}
|
||||
}
|
||||
|
||||
protected void doClose() {
|
||||
hide();
|
||||
closeHandlerOptional.ifPresent(Runnable::run);
|
||||
}
|
||||
|
||||
protected void setTruncatedMessage() {
|
||||
if (message != null && message.length() > 1200)
|
||||
truncatedMessage = StringUtils.abbreviate(message, 1200);
|
||||
|
@ -27,12 +27,13 @@ public class Notification extends Overlay<Notification> {
|
||||
public Notification() {
|
||||
width = 345; // 320 visible bg because of insets
|
||||
NotificationCenter.add(this);
|
||||
type = Type.Notification;
|
||||
}
|
||||
|
||||
public void onReadyForDisplay() {
|
||||
super.display();
|
||||
if (autoClose && autoCloseTimer == null)
|
||||
autoCloseTimer = UserThread.runAfter(this::hide, 4);
|
||||
autoCloseTimer = UserThread.runAfter(() -> doClose(), 5);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,6 +50,7 @@ public class NotificationCenter {
|
||||
|
||||
private final TradeManager tradeManager;
|
||||
private final DisputeManager disputeManager;
|
||||
private Preferences preferences;
|
||||
private final Navigation navigation;
|
||||
|
||||
private final Map<String, Subscription> disputeStateSubscriptionsMap = new HashMap<>();
|
||||
@ -66,6 +67,7 @@ public class NotificationCenter {
|
||||
public NotificationCenter(TradeManager tradeManager, DisputeManager disputeManager, Preferences preferences, Navigation navigation) {
|
||||
this.tradeManager = tradeManager;
|
||||
this.disputeManager = disputeManager;
|
||||
this.preferences = preferences;
|
||||
this.navigation = navigation;
|
||||
|
||||
EasyBind.subscribe(preferences.useAnimationsProperty(), useAnimations -> NotificationCenter.useAnimations = useAnimations);
|
||||
@ -179,21 +181,29 @@ public class NotificationCenter {
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
Notification notification = new Notification().tradeHeadLine(trade.getShortId()).message(message);
|
||||
|
||||
if (navigation.getCurrentPath() != null && !navigation.getCurrentPath().contains(PendingTradesView.class)) {
|
||||
notification.actionButtonText("Go to \"Open trades\"")
|
||||
.onAction(() -> {
|
||||
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
|
||||
UserThread.runAfter(() -> {
|
||||
String key = tradeState.name() + trade.getId();
|
||||
if (preferences.showAgain(key)) {
|
||||
Notification notification = new Notification().tradeHeadLine(trade.getShortId()).message(message);
|
||||
if (navigation.getCurrentPath() != null && !navigation.getCurrentPath().contains(PendingTradesView.class)) {
|
||||
notification.actionButtonText("Go to \"Open trades\"")
|
||||
.onAction(() -> {
|
||||
preferences.dontShowAgain(key, true);
|
||||
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
|
||||
UserThread.runAfter(() -> {
|
||||
selectItemByTradeIdConsumer.accept(trade.getId());
|
||||
}, 1);
|
||||
})
|
||||
.onClose(() -> preferences.dontShowAgain(key, true))
|
||||
.show();
|
||||
} else if (selectedTradeId != null && !trade.getId().equals(selectedTradeId)) {
|
||||
notification.actionButtonText("Select trade")
|
||||
.onAction(() -> {
|
||||
preferences.dontShowAgain(key, true);
|
||||
selectItemByTradeIdConsumer.accept(trade.getId());
|
||||
}, 1);
|
||||
})
|
||||
.show();
|
||||
} else if (selectedTradeId != null && !trade.getId().equals(selectedTradeId)) {
|
||||
notification.actionButtonText("Select trade")
|
||||
.onAction(() -> selectItemByTradeIdConsumer.accept(trade.getId()))
|
||||
.show();
|
||||
})
|
||||
.onClose(() -> preferences.dontShowAgain(key, true))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public class ContractWindow extends Overlay<ContractWindow> {
|
||||
@Inject
|
||||
public ContractWindow(BSFormatter formatter) {
|
||||
this.formatter = formatter;
|
||||
type = Type.Confirmation;
|
||||
}
|
||||
|
||||
public void show(Dispute dispute) {
|
||||
|
@ -41,6 +41,7 @@ public class DisplayAlertMessageWindow extends Overlay<DisplayAlertMessageWindow
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public DisplayAlertMessageWindow() {
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
@ -90,6 +90,8 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
this.disputeManager = disputeManager;
|
||||
this.walletService = walletService;
|
||||
this.tradeWalletService = tradeWalletService;
|
||||
|
||||
type = Type.Confirmation;
|
||||
}
|
||||
|
||||
public void show(Dispute dispute) {
|
||||
|
@ -63,6 +63,8 @@ public class EmptyWalletWindow extends Overlay<EmptyWalletWindow> {
|
||||
this.walletService = walletService;
|
||||
this.walletPasswordWindow = walletPasswordWindow;
|
||||
this.formatter = formatter;
|
||||
|
||||
type = Type.Instruction;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
@ -51,6 +51,8 @@ public class EnterPrivKeyWindow extends Overlay<EnterPrivKeyWindow> {
|
||||
public EnterPrivKeyWindow() {
|
||||
if (keyInputTextField != null)
|
||||
keyInputTextField.textProperty().addListener(changeListener);
|
||||
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
@ -76,6 +76,7 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
|
||||
this.user = user;
|
||||
this.keyRing = keyRing;
|
||||
this.navigation = navigation;
|
||||
type = Type.Confirmation;
|
||||
}
|
||||
|
||||
public void show(Offer offer, Coin tradeAmount) {
|
||||
|
@ -50,6 +50,7 @@ public class SelectDepositTxWindow extends Overlay<SelectDepositTxWindow> {
|
||||
|
||||
@Inject
|
||||
public SelectDepositTxWindow() {
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
@ -59,6 +59,7 @@ public class SendAlertMessageWindow extends Overlay<SendAlertMessageWindow> {
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public SendAlertMessageWindow() {
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
@ -19,6 +19,7 @@ public class TacWindow extends Overlay<TacWindow> {
|
||||
@Inject
|
||||
public TacWindow(Preferences preferences) {
|
||||
this.preferences = preferences;
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void showIfNeeded() {
|
||||
@ -47,7 +48,7 @@ public class TacWindow extends Overlay<TacWindow> {
|
||||
"Please be aware that using Mainnet comes with the risk to lose funds " +
|
||||
"in case of software bugs.\n" +
|
||||
"To limit the possible losses the maximum allowed trading amount and the " +
|
||||
"security deposit have been reduced to 0.1 BTC for the alpha version " +
|
||||
"security deposit have been reduced for the alpha version " +
|
||||
"when using Mainnet.")
|
||||
.actionButtonText("I understand and want to use Mainnet")
|
||||
.closeButtonText("Restart and use Testnet")
|
||||
|
@ -63,6 +63,7 @@ public class TradeDetailsWindow extends Overlay<TradeDetailsWindow> {
|
||||
this.formatter = formatter;
|
||||
this.disputeManager = disputeManager;
|
||||
this.tradeManager = tradeManager;
|
||||
type = Type.Confirmation;
|
||||
}
|
||||
|
||||
public void show(Trade trade) {
|
||||
|
@ -71,6 +71,7 @@ public class WalletPasswordWindow extends Overlay<WalletPasswordWindow> {
|
||||
@Inject
|
||||
public WalletPasswordWindow(WalletService walletService) {
|
||||
this.walletService = walletService;
|
||||
type = Type.Attention;
|
||||
}
|
||||
|
||||
public void show() {
|
||||
|
@ -83,7 +83,7 @@ class ClosedTradesViewModel extends ActivatableWithDataModel<ClosedTradesDataMod
|
||||
/* if (trade.isFailedState())
|
||||
return "Failed";
|
||||
else*/
|
||||
if (trade.getState() == Trade.State.WITHDRAW_COMPLETED) {
|
||||
if (trade.getState() == Trade.State.WITHDRAW_COMPLETED || trade.getState() == Trade.State.PAYOUT_BROAD_CASTED) {
|
||||
return "Completed";
|
||||
} else if (trade.getDisputeState() == Trade.DisputeState.DISPUTE_CLOSED) {
|
||||
return "Ticket closed";
|
||||
|
@ -102,10 +102,10 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
"When you open a support ticket the trade will be interrupted and handled by the arbitrator\n\n" +
|
||||
"Unjustified support tickets (e.g. caused by usability problems or questions) will " +
|
||||
"cause a loss of the security deposit by the trader who opened the ticket.")
|
||||
.closeButtonText("Open support ticket")
|
||||
.onClose(model.dataModel::onOpenSupportTicket)
|
||||
.actionButtonText("Cancel")
|
||||
.onAction(() -> popup.hide())
|
||||
.actionButtonText("Open support ticket")
|
||||
.onAction(model.dataModel::onOpenSupportTicket)
|
||||
.closeButtonText("Cancel")
|
||||
.onClose(() -> popup.hide())
|
||||
.show();
|
||||
}
|
||||
};
|
||||
@ -147,7 +147,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
root.getChildren().add(selectedSubView);
|
||||
else if (root.getChildren().size() == 2)
|
||||
root.getChildren().set(1, selectedSubView);
|
||||
selectedSubView.activate();
|
||||
|
||||
}
|
||||
|
||||
updateTableSelection();
|
||||
@ -156,6 +156,9 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
||||
}
|
||||
|
||||
model.onSelectedItemChanged(selectedItem);
|
||||
|
||||
if (selectedSubView != null && selectedItem != null)
|
||||
selectedSubView.activate();
|
||||
});
|
||||
|
||||
selectedTableItemSubscription = EasyBind.subscribe(table.getSelectionModel().selectedItemProperty(),
|
||||
|
@ -361,11 +361,11 @@ public abstract class TradeStepView extends AnchorPane {
|
||||
if (dispute.isSupportTicket()) {
|
||||
setSupportOpenedHeadline();
|
||||
msg = "You opened already a support ticket.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
"Please communicate in the \"Support\" screen with the arbitrator.";
|
||||
} else {
|
||||
setDisputeOpenedHeadline();
|
||||
msg = "You opened already a dispute.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
"Please communicate in the \"Support\" screen with the arbitrator.";
|
||||
}
|
||||
if (notificationGroup != null)
|
||||
notificationGroup.label.setText(msg);
|
||||
@ -380,11 +380,11 @@ public abstract class TradeStepView extends AnchorPane {
|
||||
if (dispute.isSupportTicket()) {
|
||||
setSupportOpenedHeadline();
|
||||
msg = "Your trading peer opened a support ticket due technical problems.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
"Please communicate in the \"Support\" screen with the arbitrator.";
|
||||
} else {
|
||||
setDisputeOpenedHeadline();
|
||||
msg = "Your trading peer opened a dispute.\n" +
|
||||
"Please communicate in the support section with the arbitrator.";
|
||||
"Please communicate in the \"Support\" screen with the arbitrator.";
|
||||
}
|
||||
if (notificationGroup != null)
|
||||
notificationGroup.label.setText(msg);
|
||||
|
@ -22,7 +22,6 @@ import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.components.paymentmethods.*;
|
||||
import io.bitsquare.gui.main.overlays.Overlay;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
@ -48,7 +47,6 @@ public class BuyerStep2View extends TradeStepView {
|
||||
private Label statusLabel;
|
||||
private ProgressIndicator statusProgressIndicator;
|
||||
private Subscription tradeStatePropertySubscription;
|
||||
private Overlay attentionRequiredPopup;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -67,36 +65,36 @@ public class BuyerStep2View extends TradeStepView {
|
||||
tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||
if (state == Trade.State.DEPOSIT_CONFIRMED_IN_BLOCK_CHAIN) {
|
||||
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||
String key = "startPaymentPopup";
|
||||
if (attentionRequiredPopup == null && !BitsquareApp.DEV_MODE) {
|
||||
String message = "";
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData)
|
||||
message = "Your trade has reached at least one blockchain confirmation.\n\n" +
|
||||
"You can wait for more confirmations if you want - 6 confirmations are considered as very secure.\n\n" +
|
||||
"Please transfer from your external " +
|
||||
CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()) + " wallet\n" +
|
||||
model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" +
|
||||
"Here are the payment account details of the bitcoin seller:\n" +
|
||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" +
|
||||
"You can copy & paste the values from the main screen after closing that popup.";
|
||||
else if (paymentAccountContractData != null)
|
||||
message = "Your trade has reached at least one blockchain confirmation.\n\n" +
|
||||
"You can wait for more confirmations if you want - 6 confirmations are considered as very secure.\n\n" +
|
||||
"Please go to your online banking web page and pay " +
|
||||
model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" +
|
||||
"Here are the payment account details of the bitcoin seller:\n" +
|
||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
||||
"You can copy & paste the values from the main screen after closing that popup.\n\n" +
|
||||
"Please don't forget to add the reference text \"" + trade.getShortId() +
|
||||
"\" so the receiver can assign your payment to this trade.\n\n" +
|
||||
"DO NOT use any additional notice in the reference text like " +
|
||||
"Bitcoin, Btc or Bitsquare.";
|
||||
String key = "startPayment" + trade.getId();
|
||||
log.error("key " + key);
|
||||
String message = "";
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData)
|
||||
message = "Your trade has reached at least one blockchain confirmation.\n" +
|
||||
"(You can wait for more confirmations if you want - 6 confirmations are considered as very secure.)\n\n" +
|
||||
"Please transfer from your external " +
|
||||
CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode()) + " wallet\n" +
|
||||
model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" +
|
||||
"Here are the payment account details of the bitcoin seller:\n" +
|
||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n\n" +
|
||||
"(You can copy & paste the values from the main screen after closing that popup.)";
|
||||
else if (paymentAccountContractData != null)
|
||||
message = "Your trade has reached at least one blockchain confirmation.\n" +
|
||||
"(You can wait for more confirmations if you want - 6 confirmations are considered as very secure.)\n\n" +
|
||||
"Please go to your online banking web page and pay " +
|
||||
model.formatter.formatFiatWithCode(trade.getTradeVolume()) + " to the bitcoin seller.\n\n" +
|
||||
"Here are the payment account details of the bitcoin seller:\n" +
|
||||
"" + paymentAccountContractData.getPaymentDetailsForTradePopup() + ".\n" +
|
||||
"(You can copy & paste the values from the main screen after closing that popup.)\n\n" +
|
||||
"Please don't forget to add the reference text \"" + trade.getShortId() +
|
||||
"\" so the receiver can assign your payment to this trade.\n\n" +
|
||||
"DO NOT use any additional notice in the reference text like " +
|
||||
"Bitcoin, Btc or Bitsquare.";
|
||||
|
||||
attentionRequiredPopup = new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
|
||||
if (preferences.showAgain(key)) {
|
||||
new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
|
||||
.instruction(message)
|
||||
.dontShowAgainId(key, preferences);
|
||||
|
||||
attentionRequiredPopup.show();
|
||||
.onClose(() -> preferences.dontShowAgain(key, true))
|
||||
.show();
|
||||
}
|
||||
} else if (state == Trade.State.BUYER_CONFIRMED_FIAT_PAYMENT_INITIATED) {
|
||||
showStatusInfo();
|
||||
@ -224,15 +222,16 @@ public class BuyerStep2View extends TradeStepView {
|
||||
if (model.p2PService.isBootstrapped()) {
|
||||
String key = "confirmPaymentStarted";
|
||||
if (preferences.showAgain(key) && !BitsquareApp.DEV_MODE) {
|
||||
new Popup()
|
||||
.headLine("Confirm that you have started the payment")
|
||||
Popup popup = new Popup();
|
||||
popup.headLine("Confirm that you have started the payment")
|
||||
.confirmation("Have you initiated the " + model.dataModel.getCurrencyCode() +
|
||||
" payment to your trading partner?")
|
||||
.width(700)
|
||||
.dontShowAgainId(key, preferences)
|
||||
.actionButtonText("Yes, I have started the payment")
|
||||
.closeButtonText("No")
|
||||
.onAction(this::confirmPaymentStarted)
|
||||
.closeButtonText("No")
|
||||
.onClose(popup::hide)
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
} else {
|
||||
confirmPaymentStarted();
|
||||
|
@ -19,12 +19,14 @@ package io.bitsquare.gui.main.portfolio.pendingtrades.steps.buyer;
|
||||
|
||||
import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.app.Log;
|
||||
import io.bitsquare.btc.AddressEntry;
|
||||
import io.bitsquare.btc.Restrictions;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.common.util.Tuple2;
|
||||
import io.bitsquare.gui.main.MainView;
|
||||
import io.bitsquare.gui.main.funds.FundsView;
|
||||
import io.bitsquare.gui.main.funds.transactions.TransactionsView;
|
||||
import io.bitsquare.gui.main.overlays.notifications.Notification;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
@ -116,14 +118,17 @@ public class BuyerStep5View extends TradeStepView {
|
||||
withdrawButton = addButtonAfterGroup(gridPane, ++gridRow, "Withdraw to external wallet");
|
||||
withdrawButton.setOnAction(e -> reviewWithdrawal());
|
||||
|
||||
String key = "tradeCompleteInfo";
|
||||
if (BitsquareApp.DEV_MODE)
|
||||
if (BitsquareApp.DEV_MODE) {
|
||||
withdrawAddressTextField.setText("mi8k5f9L972VgDaT4LgjAhriC9hHEPL7EW");
|
||||
else
|
||||
new Popup().headLine("Trade completed")
|
||||
.instruction("You can withdraw your funds now to your external Bitcoin wallet.")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
} else {
|
||||
String key = "tradeCompleted" + trade.getId();
|
||||
if (preferences.showAgain(key))
|
||||
new Notification().headLine("Trade completed")
|
||||
.notification("You can withdraw your funds now to your external Bitcoin wallet.")
|
||||
.onClose(() -> preferences.dontShowAgain(key, true))
|
||||
.autoClose()
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void doWithdrawal() {
|
||||
@ -131,8 +136,9 @@ public class BuyerStep5View extends TradeStepView {
|
||||
model.dataModel.onWithdrawRequest(withdrawAddressTextField.getText(),
|
||||
() -> {
|
||||
String key = "tradeCompleteWithdrawCompletedInfo";
|
||||
new Popup().headLine("Withdrawal completed").instruction("Your completed trades are stored under \"Portfolio/History\".\n" +
|
||||
"You can review all your bitcoin transactions under \"Funds/Transactions\"")
|
||||
new Popup().headLine("Withdrawal completed")
|
||||
.feedback("Your completed trades are stored under \"Portfolio/History\".\n" +
|
||||
"You can review all your bitcoin transactions under \"Funds/Transactions\"")
|
||||
.actionButtonText("Go to \"Transactions\"")
|
||||
.onAction(() -> model.dataModel.navigation.navigateTo(MainView.class, FundsView.class, TransactionsView.class))
|
||||
.dontShowAgainId(key, preferences)
|
||||
@ -151,45 +157,54 @@ public class BuyerStep5View extends TradeStepView {
|
||||
private void reviewWithdrawal() {
|
||||
Coin senderAmount = trade.getPayoutAmount();
|
||||
WalletService walletService = model.dataModel.walletService;
|
||||
String fromAddresses = walletService.getAddressEntryByOfferId(trade.getId()).getAddressString();
|
||||
AddressEntry fromAddressesEntry = walletService.getAddressEntryByOfferId(trade.getId());
|
||||
String fromAddresses = fromAddressesEntry.getAddressString();
|
||||
String toAddresses = withdrawAddressTextField.getText();
|
||||
|
||||
if (Restrictions.isAboveFixedTxFeeAndDust(senderAmount)) {
|
||||
try {
|
||||
Coin requiredFee = walletService.getRequiredFee(fromAddresses, toAddresses, senderAmount, null);
|
||||
Coin receiverAmount = senderAmount.subtract(requiredFee);
|
||||
if (BitsquareApp.DEV_MODE) {
|
||||
doWithdrawal();
|
||||
} else {
|
||||
BSFormatter formatter = model.formatter;
|
||||
String key = "reviewWithdrawalAtTradeComplete";
|
||||
if (preferences.showAgain(key)) {
|
||||
new Popup().headLine("Confirm withdrawal request")
|
||||
.confirmation("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" +
|
||||
"From address: " + fromAddresses + "\n" +
|
||||
"To receiving address: " + toAddresses + ".\n" +
|
||||
"Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" +
|
||||
"The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" +
|
||||
"Are you sure you want to withdraw that amount?")
|
||||
.actionButtonText("Yes")
|
||||
.onAction(this::doWithdrawal)
|
||||
.closeButtonText("Cancel")
|
||||
.onClose(() -> withdrawButton.setDisable(false))
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
} else {
|
||||
doWithdrawal();
|
||||
}
|
||||
|
||||
}
|
||||
} catch (AddressFormatException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
// TODO at some error situation it can be tha the funds are already paid out and we get stuck here
|
||||
// need handling to remove the trade (planned for next release)
|
||||
Coin balance = walletService.getBalanceForAddress(fromAddressesEntry.getAddress());
|
||||
if (balance.isZero()) {
|
||||
new Popup().warning("Your funds have already been withdrawn.\nPlease check the transaction history.").show();
|
||||
model.dataModel.tradeManager.addTradeToClosedTrades(trade);
|
||||
} else {
|
||||
new Popup()
|
||||
.warning("The amount to transfer is lower than the transaction fee and the min. possible tx value (dust).")
|
||||
.show();
|
||||
if (Restrictions.isAboveFixedTxFeeAndDust(senderAmount) && !toAddresses.isEmpty()) {
|
||||
try {
|
||||
Coin requiredFee = walletService.getRequiredFee(fromAddresses, toAddresses, senderAmount, null);
|
||||
Coin receiverAmount = senderAmount.subtract(requiredFee);
|
||||
if (BitsquareApp.DEV_MODE) {
|
||||
doWithdrawal();
|
||||
} else {
|
||||
BSFormatter formatter = model.formatter;
|
||||
String key = "reviewWithdrawalAtTradeComplete";
|
||||
if (preferences.showAgain(key)) {
|
||||
new Popup().headLine("Confirm withdrawal request")
|
||||
.confirmation("Sending: " + formatter.formatCoinWithCode(senderAmount) + "\n" +
|
||||
"From address: " + fromAddresses + "\n" +
|
||||
"To receiving address: " + toAddresses + ".\n" +
|
||||
"Required transaction fee is: " + formatter.formatCoinWithCode(requiredFee) + "\n\n" +
|
||||
"The recipient will receive: " + formatter.formatCoinWithCode(receiverAmount) + "\n\n" +
|
||||
"Are you sure you want to proceed with the withdrawal?")
|
||||
.closeButtonText("Cancel")
|
||||
.onClose(() -> withdrawButton.setDisable(false))
|
||||
.actionButtonText("Yes")
|
||||
.onAction(this::doWithdrawal)
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
} else {
|
||||
doWithdrawal();
|
||||
}
|
||||
|
||||
}
|
||||
} catch (AddressFormatException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
new Popup()
|
||||
.warning("The amount to transfer is lower than the transaction fee and the min. possible tx value (dust).")
|
||||
.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ import io.bitsquare.app.BitsquareApp;
|
||||
import io.bitsquare.common.util.Tuple3;
|
||||
import io.bitsquare.gui.components.TextFieldWithCopyIcon;
|
||||
import io.bitsquare.gui.components.TitledGroupBg;
|
||||
import io.bitsquare.gui.main.overlays.Overlay;
|
||||
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel;
|
||||
import io.bitsquare.gui.main.portfolio.pendingtrades.steps.TradeStepView;
|
||||
@ -49,7 +48,6 @@ public class SellerStep3View extends TradeStepView {
|
||||
private Label statusLabel;
|
||||
private ProgressIndicator statusProgressIndicator;
|
||||
private Subscription tradeStatePropertySubscription;
|
||||
private Overlay attentionRequiredPopup;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -67,34 +65,33 @@ public class SellerStep3View extends TradeStepView {
|
||||
tradeStatePropertySubscription = EasyBind.subscribe(trade.stateProperty(), state -> {
|
||||
if (state == Trade.State.SELLER_RECEIVED_FIAT_PAYMENT_INITIATED_MSG) {
|
||||
PaymentAccountContractData paymentAccountContractData = model.dataModel.getSellersPaymentAccountContractData();
|
||||
String key = "confirmPaymentPopup";
|
||||
if (attentionRequiredPopup == null && !BitsquareApp.DEV_MODE) {
|
||||
String message;
|
||||
String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume());
|
||||
String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode());
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData) {
|
||||
String address = ((BlockChainAccountContractData) paymentAccountContractData).getAddress();
|
||||
message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" +
|
||||
"Please check on your favorite " + currencyName +
|
||||
" blockchain explorer if the transaction to your receiving address\n" +
|
||||
"" + address + "\n" +
|
||||
"has already sufficient blockchain confirmations.\n" +
|
||||
"The payment amount has to be " + tradeAmountWithCode + "\n\n" +
|
||||
"You can copy & paste your " + currencyName + " address from the main screen after " +
|
||||
"closing that popup.";
|
||||
} else {
|
||||
message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" +
|
||||
"Please go to your online banking web page and check if you have received " +
|
||||
tradeAmountWithCode + " from the bitcoin buyer.\n\n" +
|
||||
"The reference text of the transaction is: \"" + trade.getShortId() + "\"";
|
||||
}
|
||||
attentionRequiredPopup = new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
|
||||
.instruction(message)
|
||||
.dontShowAgainId(key, preferences);
|
||||
|
||||
attentionRequiredPopup.show();
|
||||
|
||||
String key = "confirmPayment" + trade.getId();
|
||||
String message;
|
||||
String tradeAmountWithCode = model.formatter.formatFiatWithCode(trade.getTradeVolume());
|
||||
String currencyName = CurrencyUtil.getNameByCode(trade.getOffer().getCurrencyCode());
|
||||
if (paymentAccountContractData instanceof BlockChainAccountContractData) {
|
||||
String address = ((BlockChainAccountContractData) paymentAccountContractData).getAddress();
|
||||
message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" +
|
||||
"Please check on your favorite " + currencyName +
|
||||
" blockchain explorer if the transaction to your receiving address\n" +
|
||||
"" + address + "\n" +
|
||||
"has already sufficient blockchain confirmations.\n" +
|
||||
"The payment amount has to be " + tradeAmountWithCode + "\n\n" +
|
||||
"You can copy & paste your " + currencyName + " address from the main screen after " +
|
||||
"closing that popup.";
|
||||
} else {
|
||||
message = "Your trading partner has confirmed that he initiated the " + currencyName + " payment.\n\n" +
|
||||
"Please go to your online banking web page and check if you have received " +
|
||||
tradeAmountWithCode + " from the bitcoin buyer.\n\n" +
|
||||
"The reference text of the transaction is: \"" + trade.getShortId() + "\"";
|
||||
}
|
||||
if (preferences.showAgain(key)) {
|
||||
new Popup().headLine("Attention required for trade with ID " + trade.getShortId())
|
||||
.instruction(message)
|
||||
.onClose(() -> preferences.dontShowAgain(key, true))
|
||||
.show();
|
||||
}
|
||||
|
||||
} else if (state == Trade.State.SELLER_CONFIRMED_FIAT_PAYMENT_RECEIPT) {
|
||||
showStatusInfo();
|
||||
statusLabel.setText("Sending confirmation...");
|
||||
@ -238,10 +235,10 @@ public class SellerStep3View extends TradeStepView {
|
||||
"Please note that as soon you have confirmed the receipt, the locked trade amount will be released " +
|
||||
"to the bitcoin buyer and the security deposit will be refunded.")
|
||||
.width(700)
|
||||
.dontShowAgainId(key, preferences)
|
||||
.actionButtonText("Yes, I have received the payment")
|
||||
.closeButtonText("Cancel")
|
||||
.onAction(this::confirmPaymentReceived)
|
||||
.closeButtonText("Cancel")
|
||||
.dontShowAgainId(key, preferences)
|
||||
.show();
|
||||
} else {
|
||||
confirmPaymentReceived();
|
||||
|
@ -44,7 +44,6 @@ import javafx.util.Callback;
|
||||
import javafx.util.StringConverter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
|
||||
import static io.bitsquare.gui.util.FormBuilder.*;
|
||||
|
||||
@ -54,7 +53,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
|
||||
// not supported yet
|
||||
//private ComboBox<String> btcDenominationComboBox;
|
||||
private ComboBox<BlockChainExplorer> blockChainExplorerComboBox;
|
||||
private ComboBox<String> userLanguageComboBox;
|
||||
// private ComboBox<String> userLanguageComboBox;
|
||||
private ComboBox<TradeCurrency> preferredTradeCurrencyComboBox;
|
||||
|
||||
private CheckBox useAnimationsCheckBox, autoSelectArbitratorsCheckBox;
|
||||
@ -275,11 +274,11 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
|
||||
}
|
||||
|
||||
private void initializeOtherOptions() {
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 3, "General preferences", Layout.GROUP_DISTANCE);
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 2, "General preferences", Layout.GROUP_DISTANCE);
|
||||
GridPane.setColumnSpan(titledGroupBg, 4);
|
||||
userLanguageComboBox = addLabelComboBox(root, gridRow, "Language:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
// userLanguageComboBox = addLabelComboBox(root, gridRow, "Language:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
// btcDenominationComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin denomination:").second;
|
||||
blockChainExplorerComboBox = addLabelComboBox(root, ++gridRow, "Bitcoin block explorer:").second;
|
||||
blockChainExplorerComboBox = addLabelComboBox(root, gridRow, "Bitcoin block explorer:", Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
autoSelectArbitratorsCheckBox = addLabelCheckBox(root, ++gridRow, "Auto select arbitrators:", "").second;
|
||||
|
||||
// TODO need a bit extra work to separate trade and non trade tx fees before it can be used
|
||||
@ -352,7 +351,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
|
||||
btcDenominationComboBox.getSelectionModel().select(getBtcDenomination());
|
||||
btcDenominationComboBox.setOnAction(e -> onSelectBtcDenomination(btcDenominationComboBox.getSelectionModel().getSelectedItem()));*/
|
||||
|
||||
userLanguageComboBox.setItems(languageCodes);
|
||||
/* userLanguageComboBox.setItems(languageCodes);
|
||||
userLanguageComboBox.getSelectionModel().select(preferences.getPreferredLocale().getLanguage());
|
||||
userLanguageComboBox.setConverter(new StringConverter<String>() {
|
||||
@Override
|
||||
@ -368,7 +367,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
|
||||
userLanguageComboBox.setOnAction(e -> {
|
||||
String code = userLanguageComboBox.getSelectionModel().getSelectedItem();
|
||||
preferences.setPreferredLocale(new Locale(code, preferences.getPreferredLocale().getCountry()));
|
||||
});
|
||||
});*/
|
||||
|
||||
|
||||
blockChainExplorerComboBox.setItems(blockExplorers);
|
||||
@ -410,7 +409,7 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Activatab
|
||||
|
||||
private void deactivateOtherOptions() {
|
||||
//btcDenominationComboBox.setOnAction(null);
|
||||
userLanguageComboBox.setOnAction(null);
|
||||
// userLanguageComboBox.setOnAction(null);
|
||||
blockChainExplorerComboBox.setOnAction(null);
|
||||
// transactionFeeInputTextField.textProperty().unbind();
|
||||
/// transactionFeeInputTextField.focusedProperty().removeListener(transactionFeeFocusedListener);
|
||||
|
@ -35,7 +35,7 @@ public class Transitions {
|
||||
public final static int DEFAULT_DURATION = 600;
|
||||
|
||||
private final Preferences preferences;
|
||||
private Timeline removeBlurTimeLine;
|
||||
private Timeline removeEffectTimeLine;
|
||||
|
||||
@Inject
|
||||
public Transitions(Preferences preferences) {
|
||||
@ -91,65 +91,61 @@ public class Transitions {
|
||||
|
||||
// Blur
|
||||
public void blur(Node node) {
|
||||
blur(node, DEFAULT_DURATION, true, false, 15);
|
||||
blur(node, DEFAULT_DURATION, -0.1, false, 15);
|
||||
}
|
||||
|
||||
public void blur(Node node, int duration, boolean useDarken, boolean removeNode, double blurRadius) {
|
||||
if (removeBlurTimeLine != null)
|
||||
removeBlurTimeLine.stop();
|
||||
public void blur(Node node, int duration, double brightness, boolean removeNode, double blurRadius) {
|
||||
if (removeEffectTimeLine != null)
|
||||
removeEffectTimeLine.stop();
|
||||
|
||||
node.setMouseTransparent(true);
|
||||
GaussianBlur blur = new GaussianBlur(0.0);
|
||||
Timeline timeline = new Timeline();
|
||||
KeyValue kv1 = new KeyValue(blur.radiusProperty(), blurRadius);
|
||||
KeyFrame kf1 = new KeyFrame(Duration.millis(getDuration(duration)), kv1);
|
||||
|
||||
if (useDarken) {
|
||||
ColorAdjust darken = new ColorAdjust();
|
||||
darken.setBrightness(0.0);
|
||||
blur.setInput(darken);
|
||||
|
||||
KeyValue kv2 = new KeyValue(darken.brightnessProperty(), -0.1);
|
||||
KeyFrame kf2 = new KeyFrame(Duration.millis(getDuration(duration)), kv2);
|
||||
timeline.getKeyFrames().addAll(kf1, kf2);
|
||||
} else {
|
||||
timeline.getKeyFrames().addAll(kf1);
|
||||
}
|
||||
ColorAdjust darken = new ColorAdjust();
|
||||
darken.setBrightness(0.0);
|
||||
blur.setInput(darken);
|
||||
KeyValue kv2 = new KeyValue(darken.brightnessProperty(), brightness);
|
||||
KeyFrame kf2 = new KeyFrame(Duration.millis(getDuration(duration)), kv2);
|
||||
timeline.getKeyFrames().addAll(kf1, kf2);
|
||||
node.setEffect(blur);
|
||||
if (removeNode) timeline.setOnFinished(actionEvent -> UserThread.execute(() -> ((Pane) (node.getParent()))
|
||||
.getChildren().remove(node)));
|
||||
timeline.play();
|
||||
}
|
||||
|
||||
public void removeBlur(Node node) {
|
||||
removeBlur(node, DEFAULT_DURATION, false);
|
||||
// Darken
|
||||
public void darken(Node node, int duration, boolean removeNode) {
|
||||
blur(node, duration, -0.2, removeNode, 0);
|
||||
}
|
||||
|
||||
private void removeBlur(Node node, int duration, boolean useDarken) {
|
||||
public void removeEffect(Node node) {
|
||||
removeEffect(node, DEFAULT_DURATION);
|
||||
}
|
||||
|
||||
private void removeEffect(Node node, int duration) {
|
||||
if (node != null) {
|
||||
node.setMouseTransparent(false);
|
||||
removeEffectTimeLine = new Timeline();
|
||||
GaussianBlur blur = (GaussianBlur) node.getEffect();
|
||||
if (blur != null) {
|
||||
removeBlurTimeLine = new Timeline();
|
||||
KeyValue kv1 = new KeyValue(blur.radiusProperty(), 0.0);
|
||||
KeyFrame kf1 = new KeyFrame(Duration.millis(getDuration(duration)), kv1);
|
||||
removeEffectTimeLine.getKeyFrames().add(kf1);
|
||||
|
||||
|
||||
if (useDarken) {
|
||||
ColorAdjust darken = (ColorAdjust) blur.getInput();
|
||||
|
||||
KeyValue kv2 = new KeyValue(darken.brightnessProperty(), 0.0);
|
||||
KeyFrame kf2 = new KeyFrame(Duration.millis(getDuration(duration)), kv2);
|
||||
removeBlurTimeLine.getKeyFrames().addAll(kf1, kf2);
|
||||
} else {
|
||||
removeBlurTimeLine.getKeyFrames().addAll(kf1);
|
||||
}
|
||||
|
||||
removeBlurTimeLine.setOnFinished(actionEvent -> {
|
||||
ColorAdjust darken = (ColorAdjust) blur.getInput();
|
||||
KeyValue kv2 = new KeyValue(darken.brightnessProperty(), 0.0);
|
||||
KeyFrame kf2 = new KeyFrame(Duration.millis(getDuration(duration)), kv2);
|
||||
removeEffectTimeLine.getKeyFrames().add(kf2);
|
||||
removeEffectTimeLine.setOnFinished(actionEvent -> {
|
||||
node.setEffect(null);
|
||||
removeBlurTimeLine = null;
|
||||
removeEffectTimeLine = null;
|
||||
});
|
||||
removeBlurTimeLine.play();
|
||||
removeEffectTimeLine.play();
|
||||
} else {
|
||||
node.setEffect(null);
|
||||
removeEffectTimeLine = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user