Fix missing spinner, add different popup style

This commit is contained in:
Manfred Karrer 2016-03-08 01:25:26 +01:00
parent bbe874c920
commit b67a80d658
14 changed files with 322 additions and 124 deletions

View file

@ -53,6 +53,8 @@ bg color of non edit textFields: fafafa
-bs-smooth-red: #ed7157;
-bs-soft-red: #fe5e1c;
-bs-soft-red2: #f35e1c;
-bs-soft-red3: #fa6f25;
-bs-yellow2: #f7ac03;
-bs-warning: -bs-orange;
@ -955,15 +957,24 @@ textfield */
-fx-font-size: 14;
-fx-text-fill: #333;
-fx-background-color: white;
-fx-background-radius: 5 5 5 5;
-fx-background-radius: 10 10 10 10;
-fx-background-insets: 10;
-fx-effect: dropshadow(gaussian, #999, 10, 0, 0, 0);
}
#popup-bg-top {
-fx-font-size: 14;
-fx-text-fill: #333;
-fx-background-color: white;
-fx-background-radius: 0 0 10 10;
-fx-background-insets: 10;
-fx-effect: dropshadow(gaussian, #999, 10, 0, 0, 0);
}
#notification-popup-headline {
-fx-font-size: 12;
-fx-font-size: 13;
-fx-font-weight: bold;
-fx-text-fill: #3c3c3c;
-fx-text-fill: #333;
}
#notification-popup-bg {
@ -972,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, #000000, 15, 0, 2, 2);
-fx-effect: dropshadow(gaussian, #666, 10, 0, 2, 2);
}
.popup-icon-information {

View file

@ -35,6 +35,8 @@ import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import static io.bitsquare.gui.util.FormBuilder.*;
public abstract class PaymentMethodForm {
@ -101,20 +103,22 @@ public abstract class PaymentMethodForm {
}
public static void addAllowedPeriod(GridPane gridPane, int gridRow,
PaymentAccountContractData paymentAccountContractData, String dateFromBlocks) {
long hours = paymentAccountContractData.getMaxTradePeriod() / 6;
String displayText;
if (hours == 1)
displayText = hours + " hour";
else
displayText = hours + " hours";
if (hours == 24)
displayText = "1 day";
if (hours > 24)
displayText = hours / 24 + " days";
@Nullable PaymentAccountContractData paymentAccountContractData, String dateFromBlocks) {
if (paymentAccountContractData != null) {
long hours = paymentAccountContractData.getMaxTradePeriod() / 6;
String displayText;
if (hours == 1)
displayText = hours + " hour";
else
displayText = hours + " hours";
if (hours == 24)
displayText = "1 day";
if (hours > 24)
displayText = hours / 24 + " days";
addLabelTextField(gridPane, gridRow, "Max. allowed trade period / date:", displayText + " / " + dateFromBlocks);
addLabelTextField(gridPane, gridRow, "Max. allowed trade period / date:", displayText + " / " + dateFromBlocks);
}
}
protected void addAllowedPeriod() {

View file

@ -70,6 +70,10 @@ public class MainView extends InitializableView<StackPane, MainViewModel> {
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, true, false, 5);
}
public static void blurUltraLight() {
transitions.blur(MainView.rootContainer, Transitions.DEFAULT_DURATION, true, false, 2);
}
public static void removeBlur() {
transitions.removeBlur(MainView.rootContainer);
}

View file

@ -209,7 +209,7 @@ public class SeedWordsView extends ActivatableView<GridPane, Void> {
new Popup()
.warning("Your bitcoin wallet is encrypted.\n\n" +
"After restore, the wallet will no longer be encrypted and you must set a new password.")
.closeButtonText("I got it")
.closeButtonText("I understand")
.onClose(() -> doRestore()).show();
} else {
doRestore();

View file

@ -94,7 +94,7 @@ public class FundsView extends ActivatableViewAndModel<TabPane, Activatable> {
"traders.")
.closeButtonText("I want to learn more")
.onClose(() -> Utilities.openWebPage("https://bitsquare.io/faq"))
.actionButtonText("I got it")
.actionButtonText("I understand")
.onAction(() -> {
})
.dontShowAgainId(key, preferences)

View file

@ -245,7 +245,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
}
}
private void onShowFundsScreen() {
private void onShowPayFundsScreen() {
model.onShowPayFundsScreen();
amountTextField.setMouseTransparent(true);
minAmountTextField.setMouseTransparent(true);
priceTextField.setMouseTransparent(true);
@ -262,7 +264,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
"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 got it")
.actionButtonText("I understand")
.onAction(() -> {
})
.dontShowAgainId(key, preferences)
@ -514,26 +516,24 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class);
} else if (newValue) {
// We need a bit of delay to avoid issues with fade out/fade in of 2 popups
UserThread.runAfter(() -> {
String key = "createOfferSuccessInfo";
if (preferences.showAgain(key)) {
new Popup().headLine(BSResources.get("createOffer.success.headline"))
.feedback(BSResources.get("createOffer.success.info"))
.dontShowAgainId(key, preferences)
.actionButtonText("Go to \"My open offers\"")
.onAction(() -> {
UserThread.runAfter(() ->
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class),
100, TimeUnit.MILLISECONDS);
close();
})
.onClose(this::close)
.show();
} else {
close();
}
},
500, TimeUnit.MILLISECONDS);
String key = "createOfferSuccessInfo";
if (preferences.showAgain(key)) {
UserThread.runAfter(() -> new Popup().headLine(BSResources.get("createOffer.success.headline"))
.feedback(BSResources.get("createOffer.success.info"))
.dontShowAgainId(key, preferences)
.actionButtonText("Go to \"My open offers\"")
.onAction(() -> {
UserThread.runAfter(() ->
navigation.navigateTo(MainView.class, PortfolioView.class, OpenOffersView.class),
100, TimeUnit.MILLISECONDS);
close();
})
.onClose(this::close)
.show(),
1);
} else {
close();
}
}
};
}
@ -680,7 +680,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
cancelButton1.setId("cancel-button");
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
nextButton.setOnAction(e -> onShowFundsScreen());
nextButton.setOnAction(e -> onShowPayFundsScreen());
}
private void addFundingGroup() {

View file

@ -100,6 +100,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
private ChangeListener<String> errorMessageListener;
private Offer offer;
private Timer timeoutTimer;
private boolean showPayFundsScreenDisplayed;
///////////////////////////////////////////////////////////////////////////////////////////
@ -155,13 +156,7 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
amountDescription = BSResources.get("createOffer.amountPriceBox.amountDescription", BSResources.get("shared.sell"));
}
if (dataModel.isWalletFunded.get()) {
isSpinnerVisible.set(false);
spinnerInfoText.set("");
} else {
spinnerInfoText.set("Waiting for funds...");
isSpinnerVisible.set(true);
}
updateSpinnerInfo();
}
@Override
@ -171,6 +166,16 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
stopTimeoutTimer();
}
private void updateSpinnerInfo() {
if (dataModel.isWalletFunded.get() || !showPayFundsScreenDisplayed) {
isSpinnerVisible.set(false);
spinnerInfoText.set("");
} else if (showPayFundsScreenDisplayed) {
spinnerInfoText.set("Waiting for funds...");
isSpinnerVisible.set(true);
}
}
private void addBindings() {
if (dataModel.getDirection() == Offer.Direction.BUY) {
volumeDescriptionLabel.bind(createStringBinding(
@ -370,6 +375,11 @@ class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel
dataModel.onCurrencySelected(tradeCurrency);
}
public void onShowPayFundsScreen() {
showPayFundsScreenDisplayed = true;
updateSpinnerInfo();
}
///////////////////////////////////////////////////////////////////////////////////////////
// Handle focus

View file

@ -220,26 +220,23 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
close();
navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class);
} else if (newValue && model.getTrade() != null && model.getTrade().errorMessageProperty().get() == null) {
UserThread.runAfter(
() -> {
String key = "takeOfferSuccessInfo";
if (preferences.showAgain(key)) {
new Popup().headLine(BSResources.get("takeOffer.success.headline"))
.feedback(BSResources.get("takeOffer.success.info"))
.actionButtonText("Go to \"Open trades\"")
.dontShowAgainId(key, preferences)
.onAction(() -> {
UserThread.runAfter(
() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class)
, 100, TimeUnit.MILLISECONDS);
close();
})
.onClose(this::close)
.show();
} else {
String key = "takeOfferSuccessInfo";
if (preferences.showAgain(key)) {
UserThread.runAfter(() -> new Popup().headLine(BSResources.get("takeOffer.success.headline"))
.feedback(BSResources.get("takeOffer.success.info"))
.actionButtonText("Go to \"Open trades\"")
.dontShowAgainId(key, preferences)
.onAction(() -> {
UserThread.runAfter(
() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class)
, 100, TimeUnit.MILLISECONDS);
close();
}
}, 500, TimeUnit.MILLISECONDS);
})
.onClose(this::close)
.show(), 1);
} else {
close();
}
}
});
@ -404,7 +401,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
private void onShowPayFundsScreen() {
model.onShowPayFundsScreen();
amountTextField.setMouseTransparent(true);
priceTextField.setMouseTransparent(true);
volumeTextField.setMouseTransparent(true);
@ -416,7 +413,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
"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 got it")
.actionButtonText("I understand")
.onAction(() -> {
})
.dontShowAgainId(key, preferences)

View file

@ -117,7 +117,6 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
addListeners();
amount.set(formatter.formatCoin(dataModel.amountAsCoin.get()));
isSpinnerVisible.set(false);
showTransactionPublishedScreen.set(false);
// when getting back to an open screen we want to re-check again
@ -198,7 +197,6 @@ class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> im
dataModel.onPaymentAccountSelected(paymentAccount);
}
public void onShowPayFundsScreen() {
showPayFundsScreenDisplayed = true;
updateSpinnerInfo();

View file

@ -25,7 +25,12 @@ import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.util.Transitions;
import io.bitsquare.locale.BSResources;
import io.bitsquare.user.Preferences;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.beans.value.ChangeListener;
import javafx.collections.ObservableList;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
@ -37,6 +42,7 @@ import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.stage.Window;
import javafx.util.Duration;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -110,40 +116,34 @@ public abstract class Overlay<T extends Overlay> {
public void hide() {
animateHide(() -> {
if (owner == null)
owner = MainView.getRootContainer();
Scene rootScene = owner.getScene();
if (rootScene != null) {
Window window = rootScene.getWindow();
window.xProperty().removeListener(positionListener);
window.yProperty().removeListener(positionListener);
window.widthProperty().removeListener(positionListener);
removeEffectFromBackground();
if (centerTime != null)
centerTime.stop();
if (stage != null)
stage.hide();
else
log.warn("Stage is null");
removeEffectFromBackground();
if (stage != null)
stage.hide();
else
log.warn("Stage is null");
cleanup();
onHidden();
}
cleanup();
onHidden();
});
}
protected void onHidden() {
}
protected void animateHide(Runnable onFinishedHandler) {
onFinishedHandler.run();
}
protected void cleanup() {
if (centerTime != null)
centerTime.stop();
if (owner == null)
owner = MainView.getRootContainer();
Scene rootScene = owner.getScene();
if (rootScene != null) {
Window window = rootScene.getWindow();
window.xProperty().removeListener(positionListener);
window.yProperty().removeListener(positionListener);
window.widthProperty().removeListener(positionListener);
}
}
public T onClose(Runnable closeHandler) {
@ -273,7 +273,6 @@ public abstract class Overlay<T extends Overlay> {
return (T) this;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Protected
///////////////////////////////////////////////////////////////////////////////////////////
@ -338,29 +337,55 @@ public abstract class Overlay<T extends Overlay> {
}
}
protected void animateDisplay() {
}
protected void setModality() {
stage.initOwner(owner.getScene().getWindow());
stage.initModality(Modality.WINDOW_MODAL);
}
protected void applyStyles() {
gridPane.setId("popup-bg");
if (headLineLabel != null)
headLineLabel.setId("popup-headline");
}
protected void addEffectToBackground() {
MainView.blurLight();
}
protected void removeEffectFromBackground() {
MainView.removeBlur();
protected void animateHide(Runnable onFinishedHandler) {
if ("backgroundInfo".equals(type))
animateToTop(onFinishedHandler);
else
animateToCenter(onFinishedHandler);
}
protected void layout() {
if ("backgroundInfo".equals(type))
layoutAtTop();
else
layoutAtCenter();
}
protected void addEffectToBackground() {
if ("backgroundInfo".equals(type))
MainView.blurUltraLight();
else
MainView.blurLight();
}
protected void animateDisplay() {
if ("backgroundInfo".equals(type))
animateFromTop();
else
animateFromCenter();
}
protected void applyStyles() {
if ("backgroundInfo".equals(type))
applyStylesTop();
else
applyStylesCenter();
}
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();
@ -372,6 +397,137 @@ public abstract class Overlay<T extends Overlay> {
}
}
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");
}
protected void setModality() {
stage.initOwner(owner.getScene().getWindow());
stage.initModality(Modality.WINDOW_MODAL);
}
protected void removeEffectFromBackground() {
MainView.removeBlur();
}
protected void addHeadLine() {
if (headLine != null) {
++rowIndex;

View file

@ -35,6 +35,21 @@ public class Notification extends Overlay<Notification> {
autoCloseTimer = UserThread.runAfter(this::hide, 4);
}
@Override
public void hide() {
animateHide(() -> {
removeEffectFromBackground();
if (stage != null)
stage.hide();
else
log.warn("Stage is null");
cleanup();
onHidden();
});
}
@Override
protected void onShow() {
NotificationManager.queueForDisplay(this);
@ -159,6 +174,7 @@ public class Notification extends Overlay<Notification> {
@Override
protected void setModality() {
stage.initOwner(owner.getScene().getWindow());
stage.initModality(Modality.NONE);
}

View file

@ -21,7 +21,7 @@ import io.bitsquare.gui.main.overlays.Overlay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Popup extends Overlay<Popup> {
public class Popup<T extends Overlay> extends Overlay<Popup> {
protected final Logger log = LoggerFactory.getLogger(this.getClass());
public void onReadyForDisplay() {
@ -37,4 +37,6 @@ public class Popup extends Overlay<Popup> {
protected void onHidden() {
PopupManager.onHidden(this);
}
}

View file

@ -9,6 +9,7 @@ import java.util.concurrent.LinkedBlockingQueue;
public class PopupManager {
private static final Logger log = LoggerFactory.getLogger(PopupManager.class);
private static final Queue<Popup> popups = new LinkedBlockingQueue<>(5);
private static Popup displayedPopup;
public static void queueForDisplay(Popup popup) {

View file

@ -97,7 +97,6 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
display();
}
public OfferDetailsWindow onPlaceOffer(Runnable placeOfferHandler) {
this.placeOfferHandlerOptional = Optional.of(placeOfferHandler);
return this;
@ -113,6 +112,12 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
// Protected
///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected void onHidden() {
if (spinner != null)
spinner.setProgress(0);
}
@Override
protected void createGridPane() {
super.createGridPane();
@ -283,10 +288,4 @@ public class OfferDetailsWindow extends Overlay<OfferDetailsWindow> {
}
});
}
@Override
protected void onHidden() {
if (spinner != null)
spinner.setProgress(0);
}
}