diff --git a/common/src/main/java/io/bitsquare/common/util/Utilities.java b/common/src/main/java/io/bitsquare/common/util/Utilities.java index e9952461d1..174d593442 100644 --- a/common/src/main/java/io/bitsquare/common/util/Utilities.java +++ b/common/src/main/java/io/bitsquare/common/util/Utilities.java @@ -44,6 +44,8 @@ import java.util.concurrent.*; public class Utilities { private static final Logger log = LoggerFactory.getLogger(Utilities.class); private static long lastTimeStamp = System.currentTimeMillis(); + public static final String LB = System.getProperty("line.separator"); + public static final String LB2 = LB + LB; public static String objectToJson(Object object) { Gson gson = new GsonBuilder() diff --git a/core/src/main/java/io/bitsquare/btc/WalletService.java b/core/src/main/java/io/bitsquare/btc/WalletService.java index b294a68db8..85d0be6b81 100644 --- a/core/src/main/java/io/bitsquare/btc/WalletService.java +++ b/core/src/main/java/io/bitsquare/btc/WalletService.java @@ -284,27 +284,24 @@ public class WalletService { // Listener /////////////////////////////////////////////////////////////////////////////////////////// - public AddressConfidenceListener addAddressConfidenceListener(AddressConfidenceListener listener) { + public void addAddressConfidenceListener(AddressConfidenceListener listener) { addressConfidenceListeners.add(listener); - return listener; } public void removeAddressConfidenceListener(AddressConfidenceListener listener) { addressConfidenceListeners.remove(listener); } - public TxConfidenceListener addTxConfidenceListener(TxConfidenceListener listener) { + public void addTxConfidenceListener(TxConfidenceListener listener) { txConfidenceListeners.add(listener); - return listener; } public void removeTxConfidenceListener(TxConfidenceListener listener) { txConfidenceListeners.remove(listener); } - public BalanceListener addBalanceListener(BalanceListener listener) { + public void addBalanceListener(BalanceListener listener) { balanceListeners.add(listener); - return listener; } public void removeBalanceListener(BalanceListener listener) { @@ -667,12 +664,12 @@ public class WalletService { private class BitsquareWalletEventListener extends AbstractWalletEventListener { @Override public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { - notifyBalanceListeners(); + notifyBalanceListeners(tx); } @Override public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { - notifyBalanceListeners(); + notifyBalanceListeners(tx); } @Override @@ -691,7 +688,7 @@ public class WalletService { txConfidenceListener.onTransactionConfidenceChanged(tx.getConfidence())); } - private void notifyBalanceListeners() { + private void notifyBalanceListeners(Transaction tx) { for (BalanceListener balanceListener : balanceListeners) { Coin balance; if (balanceListener.getAddress() != null) @@ -699,7 +696,7 @@ public class WalletService { else balance = getAvailableBalance(); - balanceListener.onBalanceChanged(balance); + balanceListener.onBalanceChanged(balance, tx); } } } diff --git a/core/src/main/java/io/bitsquare/btc/listeners/BalanceListener.java b/core/src/main/java/io/bitsquare/btc/listeners/BalanceListener.java index 09941aa10d..5d5513ed52 100644 --- a/core/src/main/java/io/bitsquare/btc/listeners/BalanceListener.java +++ b/core/src/main/java/io/bitsquare/btc/listeners/BalanceListener.java @@ -19,6 +19,7 @@ package io.bitsquare.btc.listeners; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; public class BalanceListener { private Address address; @@ -35,6 +36,6 @@ public class BalanceListener { } @SuppressWarnings("UnusedParameters") - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { } } \ No newline at end of file diff --git a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SetupDepositBalanceListener.java b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SetupDepositBalanceListener.java index a83a3ae2ff..189732bee5 100644 --- a/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SetupDepositBalanceListener.java +++ b/core/src/main/java/io/bitsquare/trade/protocol/trade/tasks/offerer/SetupDepositBalanceListener.java @@ -26,6 +26,7 @@ import io.bitsquare.trade.Trade; import io.bitsquare.trade.protocol.trade.tasks.TradeTask; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; import org.slf4j.Logger; @@ -51,12 +52,12 @@ public class SetupDepositBalanceListener extends TradeTask { WalletService walletService = processModel.getWalletService(); Address address = walletService.getAddressEntryByOfferId(trade.getId()).getAddress(); - balanceListener = walletService.addBalanceListener(new BalanceListener(address) { + balanceListener = new BalanceListener(address) { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(balance); } - }); + }; walletService.addBalanceListener(balanceListener); tradeStateSubscription = EasyBind.subscribe(trade.stateProperty(), newValue -> { diff --git a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java index 54038068a8..1f73cac543 100644 --- a/gui/src/main/java/io/bitsquare/app/BitsquareApp.java +++ b/gui/src/main/java/io/bitsquare/app/BitsquareApp.java @@ -153,7 +153,7 @@ public class BitsquareApp extends Application { mainView.setPersistedFilesCorrupted(corruptedDatabaseFiles); });*/ - scene = new Scene(mainView.getRoot(), 1100, 740); + scene = new Scene(mainView.getRoot(), 1060, 740); scene.getStylesheets().setAll( "/io/bitsquare/gui/bitsquare.css", "/io/bitsquare/gui/images.css"); diff --git a/gui/src/main/java/io/bitsquare/gui/bitsquare.css b/gui/src/main/java/io/bitsquare/gui/bitsquare.css index 297987a992..c6fca62f6c 100644 --- a/gui/src/main/java/io/bitsquare/gui/bitsquare.css +++ b/gui/src/main/java/io/bitsquare/gui/bitsquare.css @@ -36,7 +36,6 @@ bg color of non edit textFields: fafafa -bs-red-soft: derive(-bs-error-red, 60%); -bs-orange: #dd8f05; - -bs-blue-transparent: #0f87c344; -bs-green-transparent: #00aa3344; @@ -678,10 +677,6 @@ textfield */ -fx-background-color: -bs-content-bg-grey; } - - - - /* TitledGroupBg */ #titled-group-bg-label { -fx-font-weight: bold; @@ -876,3 +871,22 @@ textfield */ -fx-font-size: 16; -fx-alignment: center; } + +/******************************************************************************************************************** + * + * Popups + * + ********************************************************************************************************************/ + +#popup-headline { + -fx-font-size: 18; + -fx-text-fill: #333; +} + +#popup-message { + -fx-font-size: 15; +} + +#popup-button { + -fx-font-size: 15; +} \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/gui/components/BalanceTextField.java b/gui/src/main/java/io/bitsquare/gui/components/BalanceTextField.java index 7ca5674032..601cd38340 100644 --- a/gui/src/main/java/io/bitsquare/gui/components/BalanceTextField.java +++ b/gui/src/main/java/io/bitsquare/gui/components/BalanceTextField.java @@ -28,6 +28,7 @@ import javafx.scene.layout.AnchorPane; import javafx.scene.paint.Color; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; public class BalanceTextField extends AnchorPane { @@ -64,7 +65,7 @@ public class BalanceTextField extends AnchorPane { balanceListener = new BalanceListener(address) { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(balance); } }; @@ -72,7 +73,7 @@ public class BalanceTextField extends AnchorPane { updateBalance(walletService.getBalanceForAddress(address)); } - public void disarm() { + public void cleanup() { walletService.removeBalanceListener(balanceListener); } diff --git a/gui/src/main/java/io/bitsquare/gui/components/BalanceWithConfirmationTextField.java b/gui/src/main/java/io/bitsquare/gui/components/BalanceWithConfirmationTextField.java index 6ca5ac9b75..2bdd4f0777 100644 --- a/gui/src/main/java/io/bitsquare/gui/components/BalanceWithConfirmationTextField.java +++ b/gui/src/main/java/io/bitsquare/gui/components/BalanceWithConfirmationTextField.java @@ -31,11 +31,14 @@ import javafx.scene.layout.AnchorPane; import javafx.scene.paint.Color; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionConfidence; public class BalanceWithConfirmationTextField extends AnchorPane { private static WalletService walletService; + private BalanceListener balanceListener; + private AddressConfidenceListener confidenceListener; public static void setWalletService(WalletService walletService) { BalanceWithConfirmationTextField.walletService = walletService; @@ -77,22 +80,29 @@ public class BalanceWithConfirmationTextField extends AnchorPane { getChildren().addAll(textField, progressIndicator); } + public void cleanup() { + walletService.removeBalanceListener(balanceListener); + walletService.removeAddressConfidenceListener(confidenceListener); + } + public void setup(Address address, BSFormatter formatter) { this.formatter = formatter; - walletService.addAddressConfidenceListener(new AddressConfidenceListener(address) { + confidenceListener = new AddressConfidenceListener(address) { @Override public void onTransactionConfidenceChanged(TransactionConfidence confidence) { updateConfidence(confidence); } - }); + }; + walletService.addAddressConfidenceListener(confidenceListener); updateConfidence(walletService.getConfidenceForAddress(address)); - walletService.addBalanceListener(new BalanceListener(address) { + balanceListener = new BalanceListener(address) { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(balance); } - }); + }; + walletService.addBalanceListener(balanceListener); updateBalance(walletService.getBalanceForAddress(address)); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java index b89c2970bd..1b70dcd01c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/MainViewModel.java @@ -408,7 +408,7 @@ public class MainViewModel implements ViewModel { walletService.addBalanceListener(new BalanceListener() { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(); } }); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/AccountView.java b/gui/src/main/java/io/bitsquare/gui/main/account/AccountView.java index 9a950981ce..cd34cf0b27 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/AccountView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/AccountView.java @@ -42,7 +42,6 @@ public class AccountView extends ActivatableView { @FXML Tab accountSettingsTab; - private Navigation.Listener navigationListener; private ChangeListener tabChangeListener; diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/AccountViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/account/AccountViewModel.java index 151d4bc132..ee3236a5d0 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/AccountViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/AccountViewModel.java @@ -19,18 +19,10 @@ package io.bitsquare.gui.main.account; import com.google.inject.Inject; import io.bitsquare.gui.common.model.ViewModel; -import io.bitsquare.user.User; class AccountViewModel implements ViewModel { - private final User user; - @Inject - public AccountViewModel(User user) { - this.user = user; - } - - boolean getNeedRegistration() { - return user.getAccountId() == null; + public AccountViewModel() { } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java index a8f5fd2d37..1d8e1bf01b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/arbitratorregistration/ArbitratorRegistrationView.java @@ -58,6 +58,7 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel arbitratorChangeListener; private EnterPrivKeyPopup enterPrivKeyPopup; + private ListChangeListener listChangeListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -84,6 +85,8 @@ public class ArbitratorRegistrationView extends ActivatableViewAndModel) - c -> languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2)); + listChangeListener = c -> languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2); + languagesListView.getItems().addListener(listChangeListener); } private void buildUI() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionView.java index d4aed9aa6b..051593146f 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/arbitratorselection/ArbitratorSelectionView.java @@ -26,7 +26,9 @@ import io.bitsquare.gui.popups.Popup; import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.gui.util.Layout; import io.bitsquare.locale.LanguageUtil; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.ReadOnlyObjectWrapper; +import javafx.beans.value.ChangeListener; import javafx.collections.ListChangeListener; import javafx.geometry.HPos; import javafx.geometry.Insets; @@ -52,6 +54,9 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel table; private int gridRow = 0; private CheckBox autoSelectAllMatchingCheckBox; + private ListChangeListener listChangeListener; + private ListChangeListener languageCodesListChangeListener; + private ChangeListener isSelectedChangeListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -68,13 +73,12 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2); } @Override protected void activate() { - languagesListView.getItems().addListener((ListChangeListener) c -> { - languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2); - }); + languagesListView.getItems().addListener(listChangeListener); languageComboBox.setItems(model.allLanguageCodes); languagesListView.setItems(model.languageCodes); languagesListView.setPrefHeight(languagesListView.getItems().size() * Layout.LIST_ROW_HEIGHT + 2); @@ -85,6 +89,8 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel() { private final CheckBox checkBox = new CheckBox(); private TableRow tableRow; + private BooleanProperty selectedProperty; private void updateDisableState(final ArbitratorListItem item) { boolean selected = model.isAcceptedArbitrator(item.arbitrator); @@ -261,8 +268,12 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel) c -> updateDisableState(item)); - item.isSelectedProperty().addListener((observable, oldValue, newValue) -> checkBox.setSelected(newValue)); + selectedProperty = item.isSelectedProperty(); + languageCodesListChangeListener = c -> updateDisableState(item); + model.languageCodes.addListener(languageCodesListChangeListener); + + isSelectedChangeListener = (observable, oldValue, newValue) -> checkBox.setSelected(newValue); + selectedProperty.addListener(isSelectedChangeListener); checkBox.setSelected(model.isAcceptedArbitrator(item.arbitrator)); checkBox.setOnAction(e -> { @@ -281,6 +292,10 @@ public class ArbitratorSelectionView extends ActivatableViewAndModel saveButtonDisabled.set(!validate())); } - boolean requestSavePassword() { if (validate()) { savePassword(passwordField.get()); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java index 994ae8f6c3..110daca09e 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/password/PasswordView.java @@ -30,6 +30,7 @@ import io.bitsquare.gui.popups.Popup; import io.bitsquare.gui.util.Layout; import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.gui.util.validation.PasswordValidator; +import javafx.beans.value.ChangeListener; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ProgressIndicator; @@ -54,6 +55,8 @@ public class PasswordView extends ActivatableView { private TitledGroupBg headline; private int gridRow = 0; private Label repeatedPasswordLabel; + private ChangeListener passwordFieldChangeListener; + private ChangeListener repeatedPasswordFieldChangeListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -72,17 +75,13 @@ public class PasswordView extends ActivatableView { headline = addTitledGroupBg(root, gridRow, 3, ""); passwordField = addLabelPasswordTextField(root, gridRow, "Enter password:", Layout.FIRST_ROW_DISTANCE).second; passwordField.setValidator(passwordValidator); - passwordField.textProperty().addListener((observable, oldValue, newValue) -> { - validatePasswords(); - }); + passwordFieldChangeListener = (observable, oldValue, newValue) -> validatePasswords(); Tuple2 tuple2 = addLabelPasswordTextField(root, ++gridRow, "Repeat password:"); repeatedPasswordLabel = tuple2.first; repeatedPasswordField = tuple2.second; repeatedPasswordField.setValidator(passwordValidator); - repeatedPasswordField.textProperty().addListener((observable, oldValue, newValue) -> { - validatePasswords(); - }); + repeatedPasswordFieldChangeListener = (observable, oldValue, newValue) -> validatePasswords(); Tuple3 tuple = addButtonWithStatus(root, ++gridRow, "", 0); pwButton = tuple.first; @@ -105,7 +104,6 @@ public class PasswordView extends ActivatableView { else keyCrypterScrypt = ScryptUtil.getKeyCrypterScrypt(); - ScryptUtil.deriveKeyWithScrypt(keyCrypterScrypt, passwordField.getText(), aesKey -> { deriveStatusLabel.setText(""); progressIndicator.setVisible(false); @@ -169,10 +167,16 @@ public class PasswordView extends ActivatableView { @Override protected void activate() { + passwordField.textProperty().addListener(passwordFieldChangeListener); + repeatedPasswordField.textProperty().addListener(repeatedPasswordFieldChangeListener); + } @Override protected void deactivate() { + passwordField.textProperty().removeListener(passwordFieldChangeListener); + repeatedPasswordField.textProperty().removeListener(repeatedPasswordFieldChangeListener); + } private void validatePasswords() { diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/paymentsaccount/PaymentAccountView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/paymentsaccount/PaymentAccountView.java index 42bb6ba10c..699189f424 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/paymentsaccount/PaymentAccountView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/paymentsaccount/PaymentAccountView.java @@ -64,6 +64,7 @@ public class PaymentAccountView extends ActivatableViewAndModel paymentAccountListChangeListener; @Inject public PaymentAccountView(PaymentAccountViewModel model, @@ -90,6 +91,7 @@ public class PaymentAccountView extends ActivatableViewAndModel paymentAccountsComboBox.setDisable(model.getPaymentAccounts().size() == 0); } @Override @@ -102,13 +104,13 @@ public class PaymentAccountView extends ActivatableViewAndModel) c -> paymentAccountsComboBox.setDisable(model.getPaymentAccounts().size() == 0)); + model.getPaymentAccounts().addListener(paymentAccountListChangeListener); paymentAccountsComboBox.setDisable(model.getPaymentAccounts().size() == 0); } @Override protected void deactivate() { + model.getPaymentAccounts().removeListener(paymentAccountListChangeListener); paymentAccountsComboBox.setOnAction(null); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java b/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java index 89af8bb842..b5f7fba59d 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/content/seedwords/SeedWordsView.java @@ -29,6 +29,7 @@ import io.bitsquare.gui.popups.WalletPasswordPopup; import io.bitsquare.gui.util.Layout; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; +import javafx.beans.value.ChangeListener; import javafx.scene.control.Button; import javafx.scene.control.DatePicker; import javafx.scene.control.TextArea; @@ -61,6 +62,12 @@ public class SeedWordsView extends ActivatableView { private int gridRow = 0; private DeterministicSeed keyChainSeed; + private ChangeListener seedWordsValidChangeListener; + private SimpleBooleanProperty seedWordsValid; + private SimpleBooleanProperty dateValid; + private ChangeListener seedWordsTextAreaChangeListener; + private ChangeListener datePickerChangeListener; + private ChangeListener dateChangeListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -105,6 +112,11 @@ public class SeedWordsView extends ActivatableView { @Override protected void deactivate() { + seedWordsValid.removeListener(seedWordsValidChangeListener); + seedWordsTextArea.textProperty().removeListener(seedWordsTextAreaChangeListener); + dateValid.removeListener(datePickerChangeListener); + datePicker.valueProperty().removeListener(dateChangeListener); + seedWordsTextArea.setText(""); datePicker.setValue(null); restoreButton.disableProperty().unbind(); @@ -134,15 +146,18 @@ public class SeedWordsView extends ActivatableView { restoreButton.setOnAction(e -> onRestore()); BooleanProperty seedWordsEdited = new SimpleBooleanProperty(); - BooleanProperty seedWordsValid = new SimpleBooleanProperty(true); - seedWordsValid.addListener((observable, oldValue, newValue) -> { + + seedWordsValid = new SimpleBooleanProperty(true); + seedWordsValidChangeListener = (observable, oldValue, newValue) -> { if (newValue) { seedWordsTextArea.getStyleClass().remove("validation_error"); } else { seedWordsTextArea.getStyleClass().add("validation_error"); } - }); - seedWordsTextArea.textProperty().addListener((observable, oldValue, newValue) -> { + }; + seedWordsValid.addListener(seedWordsValidChangeListener); + + seedWordsTextAreaChangeListener = (observable, oldValue, newValue) -> { seedWordsEdited.set(true); try { MnemonicCode codec = new MnemonicCode(); @@ -154,18 +169,22 @@ public class SeedWordsView extends ActivatableView { if (creationDate.equals(datePicker.getValue())) datePicker.setValue(null); - }); + }; + seedWordsTextArea.textProperty().addListener(seedWordsTextAreaChangeListener); - BooleanProperty dateValid = new SimpleBooleanProperty(true); - dateValid.addListener((observable, oldValue, newValue) -> { + dateValid = new SimpleBooleanProperty(true); + datePickerChangeListener = (observable, oldValue, newValue) -> { if (newValue) datePicker.getStyleClass().remove("validation_error"); else datePicker.getStyleClass().add("validation_error"); - }); - datePicker.valueProperty().addListener((observable, oldValue, newValue) -> { + }; + dateValid.addListener(datePickerChangeListener); + + dateChangeListener = (observable, oldValue, newValue) -> { dateValid.set(newValue != null && !newValue.isAfter(LocalDate.now())); - }); + }; + datePicker.valueProperty().addListener(dateChangeListener); restoreButton.disableProperty().bind(createBooleanBinding(() -> !seedWordsValid.get() || !dateValid.get() || !seedWordsEdited.get(), seedWordsValid, dateValid, seedWordsEdited)); diff --git a/gui/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java b/gui/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java index a74e36031e..fdba49de1c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/account/settings/AccountSettingsView.java @@ -29,6 +29,7 @@ import io.bitsquare.gui.main.account.content.password.PasswordView; import io.bitsquare.gui.main.account.content.paymentsaccount.PaymentAccountView; import io.bitsquare.gui.main.account.content.seedwords.SeedWordsView; import io.bitsquare.gui.util.Colors; +import javafx.beans.value.ChangeListener; import javafx.fxml.FXML; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -95,11 +96,22 @@ public class AccountSettingsView extends ActivatableViewAndModel { selecteedViewClass = viewPath.get(3); loadView(selecteedViewClass); } + paymentAccount.activate(); + arbitratorSelection.activate(); + password.activate(); + seedWords.activate(); + backup.activate(); } @Override protected void deactivate() { navigation.removeListener(listener); + + paymentAccount.deactivate(); + arbitratorSelection.deactivate(); + password.deactivate(); + seedWords.deactivate(); + backup.deactivate(); } private void loadView(Class viewClass) { @@ -133,7 +145,14 @@ public class AccountSettingsView extends ActivatableViewAndModel { class MenuItem extends ToggleButton { + private final ChangeListener selectedPropertyChangeListener; + private final ChangeListener disablePropertyChangeListener; + private Navigation navigation; + private Class viewClass; + MenuItem(Navigation navigation, ToggleGroup toggleGroup, String title, Class viewClass, AwesomeIcon awesomeIcon) { + this.navigation = navigation; + this.viewClass = viewClass; setToggleGroup(toggleGroup); setText(title); @@ -151,10 +170,7 @@ class MenuItem extends ToggleButton { icon.setMaxWidth(25); setGraphic(icon); - setOnAction((event) -> - navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, viewClass)); - - selectedProperty().addListener((ov, oldValue, newValue) -> { + selectedPropertyChangeListener = (ov, oldValue, newValue) -> { if (newValue) { setId("account-settings-item-background-selected"); icon.setTextFill(Colors.BLUE); @@ -162,9 +178,9 @@ class MenuItem extends ToggleButton { setId("account-settings-item-background-active"); icon.setTextFill(Paint.valueOf("#333")); } - }); + }; - disableProperty().addListener((ov, oldValue, newValue) -> { + disablePropertyChangeListener = (ov, oldValue, newValue) -> { if (newValue) { setId("account-settings-item-background-disabled"); icon.setTextFill(Paint.valueOf("#ccc")); @@ -172,7 +188,19 @@ class MenuItem extends ToggleButton { setId("account-settings-item-background-active"); icon.setTextFill(Paint.valueOf("#333")); } - }); + }; + } + + public void activate() { + setOnAction((event) -> navigation.navigateTo(MainView.class, AccountView.class, AccountSettingsView.class, viewClass)); + selectedProperty().addListener(selectedPropertyChangeListener); + disableProperty().addListener(disablePropertyChangeListener); + } + + public void deactivate() { + setOnAction(null); + selectedProperty().removeListener(selectedPropertyChangeListener); + disableProperty().removeListener(disablePropertyChangeListener); } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.fxml b/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.fxml index b812d7c318..85c1b34b6a 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.fxml @@ -26,7 +26,6 @@ AnchorPane.topAnchor="0.0" xmlns:fx="http://javafx.com/fxml"> - - + diff --git a/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.java b/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.java index 6488e66c68..014ad705d0 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/disputes/DisputesView.java @@ -40,7 +40,9 @@ import javax.inject.Inject; public class DisputesView extends ActivatableViewAndModel { @FXML - Tab tradersDisputesTab, arbitratorsDisputesTab; + Tab tradersDisputesTab; + + private Tab arbitratorsDisputesTab; private final Navigation navigation; private final ArbitratorManager arbitratorManager; @@ -51,6 +53,7 @@ public class DisputesView extends ActivatableViewAndModel private Tab currentTab; private final ViewLoader viewLoader; private MapChangeListener arbitratorMapChangeListener; + private boolean isArbitrator; @Inject public DisputesView(CachingViewLoader viewLoader, Navigation navigation, ArbitratorManager arbitratorManager, KeyRing keyRing) { @@ -58,6 +61,8 @@ public class DisputesView extends ActivatableViewAndModel this.navigation = navigation; this.arbitratorManager = arbitratorManager; this.keyRing = keyRing; + + } @Override @@ -79,12 +84,16 @@ public class DisputesView extends ActivatableViewAndModel } private void updateArbitratorsDisputesTabDisableState() { - boolean isArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream() + isArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream() .filter(e -> e.getPubKeyRing() != null && e.getPubKeyRing().equals(keyRing.getPubKeyRing())) .findAny().isPresent(); - arbitratorsDisputesTab.setDisable(!isArbitrator); - if (arbitratorsDisputesTab.getContent() != null) - arbitratorsDisputesTab.getContent().setDisable(!isArbitrator); + + if (arbitratorsDisputesTab == null && isArbitrator) { + arbitratorsDisputesTab = new Tab("Arbitrators support tickets"); + arbitratorsDisputesTab.setClosable(false); + root.getTabs().add(arbitratorsDisputesTab); + tradersDisputesTab.setText("Traders support tickets"); + } } @Override @@ -96,10 +105,10 @@ public class DisputesView extends ActivatableViewAndModel root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); navigation.addListener(navigationListener); - if (root.getSelectionModel().getSelectedItem() == tradersDisputesTab) - navigation.navigateTo(MainView.class, DisputesView.class, TraderDisputeView.class); - else if (root.getSelectionModel().getSelectedItem() == arbitratorsDisputesTab) + if (arbitratorsDisputesTab != null && root.getSelectionModel().getSelectedItem() == arbitratorsDisputesTab) navigation.navigateTo(MainView.class, DisputesView.class, ArbitratorDisputeView.class); + else + navigation.navigateTo(MainView.class, DisputesView.class, TraderDisputeView.class); } @Override @@ -117,9 +126,9 @@ public class DisputesView extends ActivatableViewAndModel View view = viewLoader.load(viewClass); - if (view instanceof ArbitratorDisputeView) + if (arbitratorsDisputesTab != null && view instanceof ArbitratorDisputeView) currentTab = arbitratorsDisputesTab; - else if (view instanceof TraderDisputeView) + else currentTab = tradersDisputesTab; currentTab.setContent(view.getRoot()); diff --git a/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java b/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java index a4375a0187..55d3cc1394 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/disputes/trader/TraderDisputeView.java @@ -38,6 +38,7 @@ import io.bitsquare.gui.util.GUIUtil; import io.bitsquare.p2p.network.Connection; import io.bitsquare.trade.Trade; import io.bitsquare.trade.TradeManager; +import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.value.ChangeListener; import javafx.collections.ListChangeListener; @@ -56,6 +57,7 @@ import javafx.util.Callback; import org.reactfx.util.FxTimer; import org.reactfx.util.Timer; +import javax.annotation.Nullable; import javax.inject.Inject; import java.io.File; import java.io.FileOutputStream; @@ -92,6 +94,13 @@ public class TraderDisputeView extends ActivatableView { private VBox messagesInputBox; private ProgressIndicator sendMsgProgressIndicator; private Label sendMsgInfoLabel; + private ChangeListener arrivedPropertyListener; + private ChangeListener storedInMailboxPropertyListener; + @Nullable + private DisputeDirectMessage disputeDirectMessage; + private ListChangeListener disputeDirectMessageListListener; + private ChangeListener inputTextAreaListener; + private ChangeListener selectedDisputeClosedPropertyListener; /////////////////////////////////////////////////////////////////////////////////////////// @@ -159,6 +168,23 @@ public class TraderDisputeView extends ActivatableView { @Override protected void deactivate() { disputesTable.getSelectionModel().selectedItemProperty().removeListener(disputeChangeListener); + + if (disputeDirectMessage != null) { + disputeDirectMessage.arrivedProperty().removeListener(arrivedPropertyListener); + disputeDirectMessage.storedInMailboxProperty().removeListener(storedInMailboxPropertyListener); + } + + if (selectedDispute != null) { + selectedDispute.isClosedProperty().removeListener(selectedDisputeClosedPropertyListener); + ObservableList disputeDirectMessages = selectedDispute.getDisputeDirectMessagesAsObservableList(); + if (disputeDirectMessages != null) { + disputeDirectMessages.removeListener(disputeDirectMessageListListener); + } + } + + if (inputTextArea != null) + inputTextArea.textProperty().removeListener(inputTextAreaListener); + } protected void setFilteredListPredicate(FilteredList filteredList) { @@ -175,7 +201,12 @@ public class TraderDisputeView extends ActivatableView { } private void onSendMessage(String inputText, Dispute dispute) { - DisputeDirectMessage disputeDirectMessage = disputeManager.sendDisputeDirectMessage(dispute, inputText, new ArrayList<>(tempAttachments)); + if (disputeDirectMessage != null) { + disputeDirectMessage.arrivedProperty().removeListener(arrivedPropertyListener); + disputeDirectMessage.storedInMailboxProperty().removeListener(storedInMailboxPropertyListener); + } + + disputeDirectMessage = disputeManager.sendDisputeDirectMessage(dispute, inputText, new ArrayList<>(tempAttachments)); tempAttachments.clear(); scrollToBottom(); @@ -192,19 +223,21 @@ public class TraderDisputeView extends ActivatableView { sendMsgProgressIndicator.setManaged(true); }); - disputeDirectMessage.arrivedProperty().addListener((observable, oldValue, newValue) -> { + arrivedPropertyListener = (observable, oldValue, newValue) -> { if (newValue) { hideSendMsgInfo(timer); } - }); - disputeDirectMessage.storedInMailboxProperty().addListener((observable, oldValue, newValue) -> { + }; + disputeDirectMessage.arrivedProperty().addListener(arrivedPropertyListener); + storedInMailboxPropertyListener = (observable, oldValue, newValue) -> { if (newValue) { sendMsgInfoLabel.setVisible(true); sendMsgInfoLabel.setManaged(true); sendMsgInfoLabel.setText("Receiver is not online. Message is saved to his mailbox."); hideSendMsgInfo(timer); } - }); + }; + disputeDirectMessage.storedInMailboxProperty().addListener(storedInMailboxPropertyListener); } private void hideSendMsgInfo(Timer timer) { @@ -221,7 +254,8 @@ public class TraderDisputeView extends ActivatableView { } private void onCloseDispute(Dispute dispute) { - disputeSummaryPopup.onFinalizeDispute(() -> messagesAnchorPane.getChildren().remove(messagesInputBox)).show(dispute); + disputeSummaryPopup.onFinalizeDispute(() -> messagesAnchorPane.getChildren().remove(messagesInputBox)) + .show(dispute); } private void onRequestUpload() { @@ -275,6 +309,14 @@ public class TraderDisputeView extends ActivatableView { } private void onSelectDispute(Dispute dispute) { + if (selectedDispute != null) { + selectedDispute.isClosedProperty().removeListener(selectedDisputeClosedPropertyListener); + ObservableList disputeDirectMessages = selectedDispute.getDisputeDirectMessagesAsObservableList(); + if (disputeDirectMessages != null) { + disputeDirectMessages.removeListener(disputeDirectMessageListListener); + } + } + if (dispute == null) { if (root.getChildren().size() > 1) root.getChildren().remove(1); @@ -283,7 +325,7 @@ public class TraderDisputeView extends ActivatableView { } else if (selectedDispute != dispute) { this.selectedDispute = dispute; - boolean isTrader = disputeManager.isTrader(dispute); + boolean isTrader = disputeManager.isTrader(selectedDispute); TableGroupHeadline tableGroupHeadline = new TableGroupHeadline(); tableGroupHeadline.setText("Messages"); @@ -293,10 +335,11 @@ public class TraderDisputeView extends ActivatableView { AnchorPane.setBottomAnchor(tableGroupHeadline, 0d); AnchorPane.setLeftAnchor(tableGroupHeadline, 0d); - ObservableList list = dispute.getDisputeDirectMessagesAsObservableList(); - SortedList sortedList = new SortedList<>(list); + ObservableList disputeDirectMessages = selectedDispute.getDisputeDirectMessagesAsObservableList(); + SortedList sortedList = new SortedList<>(disputeDirectMessages); sortedList.setComparator((o1, o2) -> o1.getDate().compareTo(o2.getDate())); - list.addListener((ListChangeListener) c -> scrollToBottom()); + disputeDirectMessageListListener = c -> scrollToBottom(); + disputeDirectMessages.addListener(disputeDirectMessageListListener); messageListView = new ListView<>(sortedList); messageListView.setId("message-list-view"); messageListView.prefWidthProperty().bind(root.widthProperty()); @@ -315,11 +358,13 @@ public class TraderDisputeView extends ActivatableView { Button sendButton = new Button("Send"); sendButton.setDefaultButton(true); - sendButton.setOnAction(e -> onSendMessage(inputTextArea.getText(), dispute)); + sendButton.setOnAction(e -> onSendMessage(inputTextArea.getText(), selectedDispute)); sendButton.setDisable(true); - inputTextArea.textProperty().addListener((observable, oldValue, newValue) -> { - sendButton.setDisable(newValue.length() == 0 && tempAttachments.size() == 0 && dispute.disputeResultProperty().get() == null); - }); + inputTextAreaListener = (observable, oldValue, newValue) -> + sendButton.setDisable(newValue.length() == 0 + && tempAttachments.size() == 0 && + selectedDispute.disputeResultProperty().get() == null); + inputTextArea.textProperty().addListener(inputTextAreaListener); Button uploadButton = new Button("Add attachments"); uploadButton.setOnAction(e -> onRequestUpload()); @@ -335,19 +380,20 @@ public class TraderDisputeView extends ActivatableView { sendMsgProgressIndicator.setVisible(false); sendMsgProgressIndicator.setManaged(false); - dispute.isClosedProperty().addListener((observable, oldValue, newValue) -> { + selectedDisputeClosedPropertyListener = (observable, oldValue, newValue) -> { messagesInputBox.setVisible(!newValue); messagesInputBox.setManaged(!newValue); AnchorPane.setBottomAnchor(messageListView, newValue ? 0d : 120d); - }); - if (!dispute.isClosed()) { + }; + selectedDispute.isClosedProperty().addListener(selectedDisputeClosedPropertyListener); + if (!selectedDispute.isClosed()) { HBox buttonBox = new HBox(); buttonBox.setSpacing(10); buttonBox.getChildren().addAll(sendButton, uploadButton, sendMsgProgressIndicator, sendMsgInfoLabel); if (!isTrader) { Button closeDisputeButton = new Button("Close ticket"); - closeDisputeButton.setOnAction(e -> onCloseDispute(dispute)); + closeDisputeButton.setOnAction(e -> onCloseDispute(selectedDispute)); closeDisputeButton.setDefaultButton(true); Pane spacer = new Pane(); HBox.setHgrow(spacer, Priority.ALWAYS); @@ -375,6 +421,7 @@ public class TraderDisputeView extends ActivatableView { @Override public ListCell call(ListView list) { return new ListCell() { + public ChangeListener sendMsgProgressIndicatorListener; final Pane bg = new Pane(); final ImageView arrow = new ImageView(); final Label headerLabel = new Label(); @@ -434,14 +481,15 @@ public class TraderDisputeView extends ActivatableView { else arrow.setId("bubble_arrow_blue_right"); - sendMsgProgressIndicator.progressProperty().addListener((observable, oldValue, newValue) -> { + sendMsgProgressIndicatorListener = (observable, oldValue, newValue) -> { if ((double) oldValue == -1 && (double) newValue == 0) { if (item.arrivedProperty().get()) showArrivedIcon(); else if (item.storedInMailboxProperty().get()) showMailboxIcon(); } - }); + }; + sendMsgProgressIndicator.progressProperty().addListener(sendMsgProgressIndicatorListener); if (item.arrivedProperty().get()) showArrivedIcon(); @@ -527,6 +575,9 @@ public class TraderDisputeView extends ActivatableView { // TODO There are still some cell rendering issues on updates setGraphic(messageAnchorPane); } else { + if (sendMsgProgressIndicator != null) + sendMsgProgressIndicator.progressProperty().removeListener(sendMsgProgressIndicatorListener); + messageAnchorPane.prefWidthProperty().unbind(); AnchorPane.clearConstraints(bg); @@ -726,18 +777,26 @@ public class TraderDisputeView extends ActivatableView { return new TableCell() { + public ReadOnlyBooleanProperty closedProperty; + public ChangeListener listener; + @Override public void updateItem(final Dispute item, boolean empty) { super.updateItem(item, empty); if (item != null && !empty) { - item.isClosedProperty().addListener((observable, oldValue, newValue) -> { + listener = (observable, oldValue, newValue) -> { setText(newValue ? "Closed" : "Open"); getTableRow().setOpacity(newValue ? 0.4 : 1); - }); + }; + closedProperty = item.isClosedProperty(); + closedProperty.addListener(listener); boolean isClosed = item.isClosed(); setText(isClosed ? "Closed" : "Open"); getTableRow().setOpacity(isClosed ? 0.4 : 1); } else { + if (closedProperty != null) + closedProperty.removeListener(listener); + setText(""); } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedListItem.java b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedListItem.java index c46e303589..7d28a01554 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedListItem.java @@ -30,6 +30,7 @@ import javafx.beans.property.StringProperty; import javafx.scene.control.Label; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,13 +59,13 @@ public class ReservedListItem { // balance balanceLabel = new Label(); - balanceListener = walletService.addBalanceListener(new BalanceListener(getAddress()) { + balanceListener = new BalanceListener(getAddress()) { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(balance); } - }); - + }; + walletService.addBalanceListener(balanceListener); updateBalance(walletService.getBalanceForAddress(getAddress())); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java index 917326a506..b699346413 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/reserved/ReservedView.java @@ -43,6 +43,7 @@ import javafx.scene.control.*; import javafx.scene.layout.VBox; import javafx.util.Callback; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; import javax.inject.Inject; import java.util.Optional; @@ -95,7 +96,7 @@ public class ReservedView extends ActivatableView { table.getSortOrder().add(dateColumn); balanceListener = new BalanceListener() { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateList(); } }; diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java index 9bed80fb6f..0b6e306289 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/transactions/TransactionsListItem.java @@ -154,13 +154,13 @@ public class TransactionsListItem { Tooltip.install(progressIndicator, tooltip); if (address != null) { - txConfidenceListener = walletService.addTxConfidenceListener(new TxConfidenceListener(txId) { + txConfidenceListener = new TxConfidenceListener(txId) { @Override public void onTransactionConfidenceChanged(TransactionConfidence confidence) { updateConfidence(confidence); } - }); - + }; + walletService.addTxConfidenceListener(txConfidenceListener); updateConfidence(transaction.getConfidence()); } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalListItem.java b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalListItem.java index 12da09f175..752a5bf4aa 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalListItem.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalListItem.java @@ -24,6 +24,7 @@ import io.bitsquare.gui.util.BSFormatter; import javafx.scene.control.Label; import org.bitcoinj.core.Address; import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; public class WithdrawalListItem { private final BalanceListener balanceListener; @@ -42,12 +43,13 @@ public class WithdrawalListItem { // balance balanceLabel = new Label(); - balanceListener = walletService.addBalanceListener(new BalanceListener(getAddress()) { + balanceListener = new BalanceListener(getAddress()) { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(balance); } - }); + }; + walletService.addBalanceListener(balanceListener); updateBalance(walletService.getBalanceForAddress(getAddress())); } diff --git a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java index 0111807813..72f9bf3aa1 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/funds/withdrawal/WithdrawalView.java @@ -133,7 +133,7 @@ public class WithdrawalView extends ActivatableView { balanceListener = new BalanceListener() { @Override - public void onBalanceChanged(Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateList(); } }; diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java index 8bf08c3916..765fd56448 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/OfferView.java @@ -32,6 +32,7 @@ import io.bitsquare.gui.popups.Popup; import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.TradeCurrency; import io.bitsquare.trade.offer.Offer; +import javafx.beans.value.ChangeListener; import javafx.collections.ListChangeListener; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; @@ -46,7 +47,7 @@ public abstract class OfferView extends ActivatableView { private TakeOfferView takeOfferView; private AnchorPane createOfferPane; private AnchorPane takeOfferPane; - private Navigation.Listener listener; + private Navigation.Listener navigationListener; private Offer offer; private final ViewLoader viewLoader; @@ -56,6 +57,8 @@ public abstract class OfferView extends ActivatableView { private Tab takeOfferTab, createOfferTab, offerBookTab; private TradeCurrency tradeCurrency; private boolean createOfferViewOpen, takeOfferViewOpen; + private ChangeListener tabChangeListener; + private ListChangeListener tabListChangeListener; protected OfferView(ViewLoader viewLoader, Navigation navigation, MarketPriceFeed marketPriceFeed) { this.viewLoader = viewLoader; @@ -66,43 +69,32 @@ public abstract class OfferView extends ActivatableView { @Override protected void initialize() { - listener = viewPath -> { + navigationListener = viewPath -> { if (viewPath.size() == 3 && viewPath.indexOf(this.getClass()) == 1) loadView(viewPath.tip()); }; - } - - @Override - protected void activate() { - // We need to remove open validation error popups - // UserThread.execute needed as focus-out event is called after selectedIndexProperty changed - // TODO Find a way to do that in the InputTextField directly, but a tab change does not trigger any event... - TabPane tabPane = root; - tabPane.getSelectionModel().selectedItemProperty() - .addListener((observableValue, oldValue, newValue) -> { - UserThread.execute(InputTextField::hideErrorMessageDisplay); - if (newValue != null) { - if (newValue.equals(createOfferTab) && createOfferView != null) { - createOfferView.onTabSelected(true); - } else if (newValue.equals(takeOfferTab) && takeOfferView != null) { - takeOfferView.onTabSelected(true); - } else if (newValue.equals(offerBookTab) && offerBookView != null) { - offerBookView.onTabSelected(true); - } - } - if (oldValue != null) { - if (oldValue.equals(createOfferTab) && createOfferView != null) { - createOfferView.onTabSelected(false); - } else if (oldValue.equals(takeOfferTab) && takeOfferView != null) { - takeOfferView.onTabSelected(false); - } else if (oldValue.equals(offerBookTab) && offerBookView != null) { - offerBookView.onTabSelected(false); - } - } - }); - - // We want to get informed when a tab get closed - tabPane.getTabs().addListener((ListChangeListener) change -> { + tabChangeListener = (observableValue, oldValue, newValue) -> { + UserThread.execute(InputTextField::hideErrorMessageDisplay); + if (newValue != null) { + if (newValue.equals(createOfferTab) && createOfferView != null) { + createOfferView.onTabSelected(true); + } else if (newValue.equals(takeOfferTab) && takeOfferView != null) { + takeOfferView.onTabSelected(true); + } else if (newValue.equals(offerBookTab) && offerBookView != null) { + offerBookView.onTabSelected(true); + } + } + if (oldValue != null) { + if (oldValue.equals(createOfferTab) && createOfferView != null) { + createOfferView.onTabSelected(false); + } else if (oldValue.equals(takeOfferTab) && takeOfferView != null) { + takeOfferView.onTabSelected(false); + } else if (oldValue.equals(offerBookTab) && offerBookView != null) { + offerBookView.onTabSelected(false); + } + } + }; + tabListChangeListener = (ListChangeListener) change -> { change.next(); List removedTabs = change.getRemoved(); if (removedTabs.size() == 1) { @@ -111,17 +103,23 @@ public abstract class OfferView extends ActivatableView { else if (removedTabs.get(0).getContent().equals(takeOfferPane)) onTakeOfferViewRemoved(); } - }); + }; + } + @Override + protected void activate() { tradeCurrency = CurrencyUtil.getDefaultTradeCurrency(); - - navigation.addListener(listener); + root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); + root.getTabs().addListener(tabListChangeListener); + navigation.addListener(navigationListener); navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class); } @Override protected void deactivate() { - navigation.removeListener(listener); + navigation.removeListener(navigationListener); + root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener); + root.getTabs().removeListener(tabListChangeListener); } private void loadView(Class viewClass) { @@ -140,7 +138,7 @@ public abstract class OfferView extends ActivatableView { tabPane.getTabs().add(offerBookTab); offerBookView = (OfferBookView) view; offerBookView.onTabSelected(true); - + OfferActionHandler offerActionHandler = new OfferActionHandler() { @Override public void onCreateOffer(TradeCurrency tradeCurrency) { diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java index e3ced51e78..af772be02c 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/createoffer/CreateOfferDataModel.java @@ -46,8 +46,8 @@ import javafx.beans.property.*; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.SetChangeListener; -import org.bitcoinj.core.*; -import org.bitcoinj.script.Script; +import org.bitcoinj.core.Coin; +import org.bitcoinj.core.Transaction; import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.Fiat; import org.jetbrains.annotations.NotNull; @@ -102,7 +102,6 @@ class CreateOfferDataModel extends ActivatableDataModel { final ObservableList paymentAccounts = FXCollections.observableArrayList(); private PaymentAccount paymentAccount; - private WalletEventListener walletEventListener; private boolean isTabSelected; @@ -134,42 +133,36 @@ class CreateOfferDataModel extends ActivatableDataModel { balanceListener = new BalanceListener(getAddressEntry().getAddress()) { @Override - public void onBalanceChanged(@NotNull Coin balance) { + public void onBalanceChanged(Coin balance, Transaction tx) { updateBalance(balance); + + if (preferences.getBitcoinNetwork() == BitcoinNetwork.MAINNET) { + SettableFuture future = blockchainService.requestFee(tx.getHashAsString()); + Futures.addCallback(future, new FutureCallback() { + public void onSuccess(Coin fee) { + UserThread.execute(() -> feeFromFundingTxProperty.set(fee)); + } + + public void onFailure(@NotNull Throwable throwable) { + UserThread.execute(() -> new Popup() + .warning("We did not get a response for the request of the mining fee used " + + "in the funding transaction.\n\n" + + "Are you sure you used a sufficiently high fee of at least " + + formatter.formatCoinWithCode(FeePolicy.getMinRequiredFeeForFundingTx()) + "?") + .actionButtonText("Yes, I used a sufficiently high fee.") + .onAction(() -> feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx())) + .closeButtonText("No. Let's cancel that payment.") + .onClose(() -> feeFromFundingTxProperty.set(Coin.ZERO)) + .show()); + } + }); + } else { + feeFromFundingTxProperty.set(FeePolicy.getMinRequiredFeeForFundingTx()); + } } }; paymentAccountsChangeListener = change -> paymentAccounts.setAll(user.getPaymentAccounts()); - walletEventListener = new WalletEventListener() { - @Override - public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { - requestFeeFromBlockchain(tx.getHashAsString()); - } - - @Override - public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { - } - - @Override - public void onReorganize(Wallet wallet) { - } - - @Override - public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { - } - - @Override - public void onWalletChanged(Wallet wallet) { - } - - @Override - public void onScriptsChanged(Wallet wallet, List