Fix Remove offer bug. Add handlers to remove offer. Rename delegate to dataModel.

This commit is contained in:
Manfred Karrer 2015-03-08 00:44:55 +01:00
parent d832cfe74b
commit 3b35774b4b
22 changed files with 372 additions and 358 deletions

View file

@ -30,7 +30,7 @@ import com.google.inject.Inject;
import java.util.Currency; import java.util.Currency;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -42,7 +42,7 @@ import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.util.StringConverter; import javafx.util.StringConverter;
class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel> implements ViewModel { class FiatAccountViewModel extends ActivatableWithDataModel<FiatAccountDataModel> implements ViewModel {
private final BankAccountNumberValidator bankAccountNumberValidator; private final BankAccountNumberValidator bankAccountNumberValidator;
@ -61,26 +61,26 @@ class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel>
@Inject @Inject
public FiatAccountViewModel(FiatAccountDataModel delegate, BankAccountNumberValidator bankAccountNumberValidator) { public FiatAccountViewModel(FiatAccountDataModel dataModel, BankAccountNumberValidator bankAccountNumberValidator) {
super(delegate); super(dataModel);
this.bankAccountNumberValidator = bankAccountNumberValidator; this.bankAccountNumberValidator = bankAccountNumberValidator;
// input // input
title.bindBidirectional(delegate.title); title.bindBidirectional(dataModel.title);
holderName.bindBidirectional(delegate.holderName); holderName.bindBidirectional(dataModel.holderName);
primaryID.bindBidirectional(delegate.primaryID); primaryID.bindBidirectional(dataModel.primaryID);
secondaryID.bindBidirectional(delegate.secondaryID); secondaryID.bindBidirectional(dataModel.secondaryID);
type.bindBidirectional(delegate.type); type.bindBidirectional(dataModel.type);
country.bindBidirectional(delegate.country); country.bindBidirectional(dataModel.country);
currency.bindBidirectional(delegate.currency); currency.bindBidirectional(dataModel.currency);
primaryIDPrompt.bind(delegate.primaryIDPrompt); primaryIDPrompt.bind(dataModel.primaryIDPrompt);
secondaryIDPrompt.bind(delegate.secondaryIDPrompt); secondaryIDPrompt.bind(dataModel.secondaryIDPrompt);
selectionPrompt.set("No bank account available"); selectionPrompt.set("No bank account available");
selectionDisable.set(true); selectionDisable.set(true);
delegate.title.addListener((ov, oldValue, newValue) -> validateInput()); dataModel.title.addListener((ov, oldValue, newValue) -> validateInput());
holderName.addListener((ov, oldValue, newValue) -> validateInput()); holderName.addListener((ov, oldValue, newValue) -> validateInput());
primaryID.addListener((ov, oldValue, newValue) -> validateInput()); primaryID.addListener((ov, oldValue, newValue) -> validateInput());
secondaryID.addListener((ov, oldValue, newValue) -> validateInput()); secondaryID.addListener((ov, oldValue, newValue) -> validateInput());
@ -88,7 +88,7 @@ class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel>
@Override @Override
public void doActivate() { public void doActivate() {
delegate.allBankAccounts.addListener((ListChangeListener<BankAccount>) change -> applyAllBankAccounts()); dataModel.allBankAccounts.addListener((ListChangeListener<BankAccount>) change -> applyAllBankAccounts());
applyAllBankAccounts(); applyAllBankAccounts();
} }
@ -96,21 +96,21 @@ class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel>
InputValidator.ValidationResult requestSaveBankAccount() { InputValidator.ValidationResult requestSaveBankAccount() {
InputValidator.ValidationResult result = validateInput(); InputValidator.ValidationResult result = validateInput();
if (result.isValid) { if (result.isValid) {
delegate.saveBankAccount(); dataModel.saveBankAccount();
} }
return result; return result;
} }
void removeBankAccount() { void removeBankAccount() {
delegate.removeBankAccount(); dataModel.removeBankAccount();
} }
void addCountryToAcceptedCountriesList() { void addCountryToAcceptedCountriesList() {
delegate.addCountryToAcceptedCountriesList(); dataModel.addCountryToAcceptedCountriesList();
} }
void selectBankAccount(BankAccount bankAccount) { void selectBankAccount(BankAccount bankAccount) {
delegate.selectBankAccount(bankAccount); dataModel.selectBankAccount(bankAccount);
} }
@ -188,27 +188,27 @@ class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel>
ObservableList<BankAccountType> getAllTypes() { ObservableList<BankAccountType> getAllTypes() {
return delegate.allTypes; return dataModel.allTypes;
} }
ObservableList<BankAccount> getAllBankAccounts() { ObservableList<BankAccount> getAllBankAccounts() {
return delegate.allBankAccounts; return dataModel.allBankAccounts;
} }
ObservableList<Currency> getAllCurrencies() { ObservableList<Currency> getAllCurrencies() {
return delegate.allCurrencies; return dataModel.allCurrencies;
} }
ObservableList<Region> getAllRegions() { ObservableList<Region> getAllRegions() {
return delegate.allRegions; return dataModel.allRegions;
} }
BooleanProperty getCountryNotInAcceptedCountriesList() { BooleanProperty getCountryNotInAcceptedCountriesList() {
return delegate.countryNotInAcceptedCountriesList; return dataModel.countryNotInAcceptedCountriesList;
} }
ObservableList<Country> getAllCountriesFor(Region selectedRegion) { ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return delegate.getAllCountriesFor(selectedRegion); return dataModel.getAllCountriesFor(selectedRegion);
} }
BankAccountNumberValidator getBankAccountNumberValidator() { BankAccountNumberValidator getBankAccountNumberValidator() {
@ -217,23 +217,23 @@ class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel>
void setType(BankAccountType type) { void setType(BankAccountType type) {
delegate.setType(type); dataModel.setType(type);
validateInput(); validateInput();
} }
void setCountry(Country country) { void setCountry(Country country) {
delegate.setCountry(country); dataModel.setCountry(country);
validateInput(); validateInput();
} }
void setCurrency(Currency currency) { void setCurrency(Currency currency) {
delegate.setCurrency(currency); dataModel.setCurrency(currency);
validateInput(); validateInput();
} }
private void applyAllBankAccounts() { private void applyAllBankAccounts() {
if (delegate.allBankAccounts.isEmpty()) { if (dataModel.allBankAccounts.isEmpty()) {
selectionPrompt.set("No bank account available"); selectionPrompt.set("No bank account available");
selectionDisable.set(true); selectionDisable.set(true);
} }
@ -244,23 +244,23 @@ class FiatAccountViewModel extends ActivatableWithDelegate<FiatAccountDataModel>
} }
private InputValidator.ValidationResult validateInput() { private InputValidator.ValidationResult validateInput() {
InputValidator.ValidationResult result = bankAccountNumberValidator.validate(delegate.title.get()); InputValidator.ValidationResult result = bankAccountNumberValidator.validate(dataModel.title.get());
if (result.isValid) { if (result.isValid) {
result = bankAccountNumberValidator.validate(delegate.holderName.get()); result = bankAccountNumberValidator.validate(dataModel.holderName.get());
if (result.isValid) { if (result.isValid) {
result = bankAccountNumberValidator.validate(delegate.primaryID.get()); result = bankAccountNumberValidator.validate(dataModel.primaryID.get());
if (result.isValid) { if (result.isValid) {
result = bankAccountNumberValidator.validate(delegate.secondaryID.get()); result = bankAccountNumberValidator.validate(dataModel.secondaryID.get());
if (result.isValid) { if (result.isValid) {
if (delegate.currency.get() == null) if (dataModel.currency.get() == null)
result = new InputValidator.ValidationResult(false, result = new InputValidator.ValidationResult(false,
"You have not selected a currency"); "You have not selected a currency");
if (result.isValid) { if (result.isValid) {
if (delegate.country.get() == null) if (dataModel.country.get() == null)
result = new InputValidator.ValidationResult(false, result = new InputValidator.ValidationResult(false,
"You have not selected a country of the payments account"); "You have not selected a country of the payments account");
if (result.isValid) { if (result.isValid) {
if (delegate.type.get() == null) if (dataModel.type.get() == null)
result = new InputValidator.ValidationResult(false, result = new InputValidator.ValidationResult(false,
"You have not selected a payments method"); "You have not selected a payments method");
} }

View file

@ -27,7 +27,7 @@ import com.google.inject.Inject;
import java.util.Currency; import java.util.Currency;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -38,7 +38,7 @@ import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.util.StringConverter; import javafx.util.StringConverter;
class IrcAccountViewModel extends ActivatableWithDelegate<IrcAccountDataModel> implements ViewModel { class IrcAccountViewModel extends ActivatableWithDataModel<IrcAccountDataModel> implements ViewModel {
private final InputValidator nickNameValidator; private final InputValidator nickNameValidator;
@ -49,23 +49,23 @@ class IrcAccountViewModel extends ActivatableWithDelegate<IrcAccountDataModel> i
@Inject @Inject
public IrcAccountViewModel(IrcAccountDataModel delegate, BankAccountNumberValidator nickNameValidator) { public IrcAccountViewModel(IrcAccountDataModel dataModel, BankAccountNumberValidator nickNameValidator) {
super(delegate); super(dataModel);
this.nickNameValidator = nickNameValidator; this.nickNameValidator = nickNameValidator;
// input // input
ircNickName.bindBidirectional(delegate.nickName); ircNickName.bindBidirectional(dataModel.nickName);
type.bindBidirectional(delegate.type); type.bindBidirectional(dataModel.type);
currency.bindBidirectional(delegate.currency); currency.bindBidirectional(dataModel.currency);
delegate.nickName.addListener((ov, oldValue, newValue) -> validateInput()); dataModel.nickName.addListener((ov, oldValue, newValue) -> validateInput());
} }
InputValidator.ValidationResult requestSaveBankAccount() { InputValidator.ValidationResult requestSaveBankAccount() {
InputValidator.ValidationResult result = validateInput(); InputValidator.ValidationResult result = validateInput();
if (result.isValid) { if (result.isValid) {
delegate.saveBankAccount(); dataModel.saveBankAccount();
} }
return result; return result;
} }
@ -104,11 +104,11 @@ class IrcAccountViewModel extends ActivatableWithDelegate<IrcAccountDataModel> i
ObservableList<BankAccountType> getAllTypes() { ObservableList<BankAccountType> getAllTypes() {
return delegate.allTypes; return dataModel.allTypes;
} }
ObservableList<Currency> getAllCurrencies() { ObservableList<Currency> getAllCurrencies() {
return delegate.allCurrencies; return dataModel.allCurrencies;
} }
InputValidator getNickNameValidator() { InputValidator getNickNameValidator() {
@ -117,24 +117,24 @@ class IrcAccountViewModel extends ActivatableWithDelegate<IrcAccountDataModel> i
void setType(BankAccountType type) { void setType(BankAccountType type) {
delegate.setType(type); dataModel.setType(type);
validateInput(); validateInput();
} }
void setCurrency(Currency currency) { void setCurrency(Currency currency) {
delegate.setCurrency(currency); dataModel.setCurrency(currency);
validateInput(); validateInput();
} }
private InputValidator.ValidationResult validateInput() { private InputValidator.ValidationResult validateInput() {
InputValidator.ValidationResult result = nickNameValidator.validate(delegate.nickName.get()); InputValidator.ValidationResult result = nickNameValidator.validate(dataModel.nickName.get());
if (delegate.currency.get() == null) if (dataModel.currency.get() == null)
result = new InputValidator.ValidationResult(false, result = new InputValidator.ValidationResult(false,
"You have not selected a currency"); "You have not selected a currency");
if (result.isValid) { if (result.isValid) {
if (delegate.type.get() == null) if (dataModel.type.get() == null)
result = new InputValidator.ValidationResult(false, result = new InputValidator.ValidationResult(false,
"You have not selected a payments method"); "You have not selected a payments method");
} }

View file

@ -27,7 +27,7 @@ import org.bitcoinj.core.Coin;
import com.google.inject.Inject; import com.google.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.WithDelegate; import viewfx.model.support.WithDataModel;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -37,7 +37,7 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
class RegistrationViewModel extends WithDelegate<RegistrationDataModel> implements ViewModel { class RegistrationViewModel extends WithDataModel<RegistrationDataModel> implements ViewModel {
final BooleanProperty isPayButtonDisabled = new SimpleBooleanProperty(true); final BooleanProperty isPayButtonDisabled = new SimpleBooleanProperty(true);
final StringProperty requestPlaceOfferErrorMessage = new SimpleStringProperty(); final StringProperty requestPlaceOfferErrorMessage = new SimpleStringProperty();
@ -50,27 +50,27 @@ class RegistrationViewModel extends WithDelegate<RegistrationDataModel> implemen
@Inject @Inject
public RegistrationViewModel(RegistrationDataModel delegate, BSFormatter formatter) { public RegistrationViewModel(RegistrationDataModel dataModel, BSFormatter formatter) {
super(delegate); super(dataModel);
this.formatter = formatter; this.formatter = formatter;
if (delegate.getAddressEntry() != null) { if (dataModel.getAddressEntry() != null) {
address.set(delegate.getAddressEntry().getAddress()); address.set(dataModel.getAddressEntry().getAddress());
} }
delegate.isWalletFunded.addListener((ov, oldValue, newValue) -> { dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue) if (newValue)
validateInput(); validateInput();
}); });
validateInput(); validateInput();
delegate.payFeeSuccess.addListener((ov, oldValue, newValue) -> { dataModel.payFeeSuccess.addListener((ov, oldValue, newValue) -> {
isPayButtonDisabled.set(newValue); isPayButtonDisabled.set(newValue);
showTransactionPublishedScreen.set(newValue); showTransactionPublishedScreen.set(newValue);
isPaymentSpinnerVisible.set(false); isPaymentSpinnerVisible.set(false);
}); });
delegate.payFeeErrorMessage.addListener((ov, oldValue, newValue) -> { dataModel.payFeeErrorMessage.addListener((ov, oldValue, newValue) -> {
if (newValue != null) { if (newValue != null) {
requestPlaceOfferErrorMessage.set(newValue); requestPlaceOfferErrorMessage.set(newValue);
isPaymentSpinnerVisible.set(false); isPaymentSpinnerVisible.set(false);
@ -79,18 +79,18 @@ class RegistrationViewModel extends WithDelegate<RegistrationDataModel> implemen
} }
void payFee() { void payFee() {
delegate.payFeeErrorMessage.set(null); dataModel.payFeeErrorMessage.set(null);
delegate.payFeeSuccess.set(false); dataModel.payFeeSuccess.set(false);
isPayButtonDisabled.set(true); isPayButtonDisabled.set(true);
isPaymentSpinnerVisible.set(true); isPaymentSpinnerVisible.set(true);
delegate.payFee(); dataModel.payFee();
} }
WalletService getWalletService() { WalletService getWalletService() {
return delegate.getWalletService(); return dataModel.getWalletService();
} }
BSFormatter getFormatter() { BSFormatter getFormatter() {
@ -98,11 +98,11 @@ class RegistrationViewModel extends WithDelegate<RegistrationDataModel> implemen
} }
Coin getFeeAsCoin() { Coin getFeeAsCoin() {
return delegate.getFeeAsCoin(); return dataModel.getFeeAsCoin();
} }
String getAddressAsString() { String getAddressAsString() {
return delegate.getAddressEntry() != null ? delegate.getAddressEntry().getAddress().toString() : ""; return dataModel.getAddressEntry() != null ? dataModel.getAddressEntry().getAddress().toString() : "";
} }
String getPaymentLabel() { String getPaymentLabel() {
@ -110,16 +110,16 @@ class RegistrationViewModel extends WithDelegate<RegistrationDataModel> implemen
} }
String getFeeAsString() { String getFeeAsString() {
return formatter.formatCoinWithCode(delegate.getFeeAsCoin()); return formatter.formatCoinWithCode(dataModel.getFeeAsCoin());
} }
String getTransactionId() { String getTransactionId() {
return delegate.getTransactionId(); return dataModel.getTransactionId();
} }
private void validateInput() { private void validateInput() {
isPayButtonDisabled.set(!(delegate.isWalletFunded.get())); isPayButtonDisabled.set(!(dataModel.isWalletFunded.get()));
} }

View file

@ -26,20 +26,20 @@ import com.google.inject.Inject;
import java.util.Locale; import java.util.Locale;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
class RestrictionsViewModel extends ActivatableWithDelegate<RestrictionsDataModel> implements ViewModel { class RestrictionsViewModel extends ActivatableWithDataModel<RestrictionsDataModel> implements ViewModel {
final BooleanProperty doneButtonDisable = new SimpleBooleanProperty(true); final BooleanProperty doneButtonDisable = new SimpleBooleanProperty(true);
@Inject @Inject
public RestrictionsViewModel(RestrictionsDataModel delegate) { public RestrictionsViewModel(RestrictionsDataModel dataModel) {
super(delegate); super(dataModel);
} }
@ -49,70 +49,70 @@ class RestrictionsViewModel extends ActivatableWithDelegate<RestrictionsDataMode
} }
void addLanguage(Locale locale) { void addLanguage(Locale locale) {
delegate.addLanguage(locale); dataModel.addLanguage(locale);
updateDoneButtonDisableState(); updateDoneButtonDisableState();
} }
void removeLanguage(Locale locale) { void removeLanguage(Locale locale) {
delegate.removeLanguage(locale); dataModel.removeLanguage(locale);
updateDoneButtonDisableState(); updateDoneButtonDisableState();
} }
void addCountry(Country country) { void addCountry(Country country) {
delegate.addCountry(country); dataModel.addCountry(country);
updateDoneButtonDisableState(); updateDoneButtonDisableState();
} }
void removeCountry(Country country) { void removeCountry(Country country) {
delegate.removeCountry(country); dataModel.removeCountry(country);
updateDoneButtonDisableState(); updateDoneButtonDisableState();
} }
void removeArbitrator(Arbitrator arbitrator) { void removeArbitrator(Arbitrator arbitrator) {
delegate.removeArbitrator(arbitrator); dataModel.removeArbitrator(arbitrator);
updateDoneButtonDisableState(); updateDoneButtonDisableState();
} }
void updateArbitratorList() { void updateArbitratorList() {
delegate.updateArbitratorList(); dataModel.updateArbitratorList();
updateDoneButtonDisableState(); updateDoneButtonDisableState();
} }
ObservableList<Country> getListWithAllEuroCountries() { ObservableList<Country> getListWithAllEuroCountries() {
return delegate.getListWithAllEuroCountries(); return dataModel.getListWithAllEuroCountries();
} }
ObservableList<Country> getAllCountriesFor(Region selectedRegion) { ObservableList<Country> getAllCountriesFor(Region selectedRegion) {
return delegate.getAllCountriesFor(selectedRegion); return dataModel.getAllCountriesFor(selectedRegion);
} }
ObservableList<Locale> getLanguageList() { ObservableList<Locale> getLanguageList() {
return delegate.languageList; return dataModel.languageList;
} }
ObservableList<Region> getAllRegions() { ObservableList<Region> getAllRegions() {
return delegate.allRegions; return dataModel.allRegions;
} }
ObservableList<Locale> getAllLanguages() { ObservableList<Locale> getAllLanguages() {
return delegate.allLanguages; return dataModel.allLanguages;
} }
ObservableList<Country> getCountryList() { ObservableList<Country> getCountryList() {
return delegate.countryList; return dataModel.countryList;
} }
ObservableList<Arbitrator> getArbitratorList() { ObservableList<Arbitrator> getArbitratorList() {
return delegate.arbitratorList; return dataModel.arbitratorList;
} }
//TODO Revert size() > -1 to 0(2 later). For mock testing disabled arbitratorList test //TODO Revert size() > -1 to 0(2 later). For mock testing disabled arbitratorList test
private void updateDoneButtonDisableState() { private void updateDoneButtonDisableState() {
boolean isValid = delegate.languageList != null && delegate.languageList.size() > 0 && boolean isValid = dataModel.languageList != null && dataModel.languageList.size() > 0 &&
delegate.countryList != null && delegate.countryList.size() > 0 && dataModel.countryList != null && dataModel.countryList.size() > 0 &&
delegate.arbitratorList != null && delegate.arbitratorList.size() > -1; dataModel.arbitratorList != null && dataModel.arbitratorList.size() > -1;
doneButtonDisable.set(!isValid); doneButtonDisable.set(!isValid);
} }

View file

@ -22,24 +22,24 @@ import io.bitsquare.gui.util.BSFormatter;
import com.google.inject.Inject; import com.google.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
class ClosedTradesViewModel extends ActivatableWithDelegate<ClosedTradesDataModel> implements ViewModel { class ClosedTradesViewModel extends ActivatableWithDataModel<ClosedTradesDataModel> implements ViewModel {
private final BSFormatter formatter; private final BSFormatter formatter;
@Inject @Inject
public ClosedTradesViewModel(ClosedTradesDataModel delegate, BSFormatter formatter) { public ClosedTradesViewModel(ClosedTradesDataModel dataModel, BSFormatter formatter) {
super(delegate); super(dataModel);
this.formatter = formatter; this.formatter = formatter;
} }
public ObservableList<ClosedTradesListItem> getList() { public ObservableList<ClosedTradesListItem> getList() {
return delegate.getList(); return dataModel.getList();
} }
String getTradeId(ClosedTradesListItem item) { String getTradeId(ClosedTradesListItem item) {
@ -59,7 +59,7 @@ class ClosedTradesViewModel extends ActivatableWithDelegate<ClosedTradesDataMode
} }
String getDirectionLabel(ClosedTradesListItem item) { String getDirectionLabel(ClosedTradesListItem item) {
return (item != null) ? formatter.formatDirection(delegate.getDirection(item.getTrade().getOffer())) : ""; return (item != null) ? formatter.formatDirection(dataModel.getDirection(item.getTrade().getOffer())) : "";
} }
String getDate(ClosedTradesListItem item) { String getDate(ClosedTradesListItem item) {

View file

@ -72,7 +72,7 @@ class OffersDataModel implements Activatable, DataModel {
} }
void removeOffer(OfferListItem item) { void removeOffer(OfferListItem item) {
tradeManager.removeOffer(item.getOffer()); tradeManager.requestRemoveOffer(item.getOffer());
} }

View file

@ -22,30 +22,30 @@ import io.bitsquare.gui.util.BSFormatter;
import com.google.inject.Inject; import com.google.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
class OffersViewModel extends ActivatableWithDelegate<OffersDataModel> implements ViewModel { class OffersViewModel extends ActivatableWithDataModel<OffersDataModel> implements ViewModel {
private final BSFormatter formatter; private final BSFormatter formatter;
@Inject @Inject
public OffersViewModel(OffersDataModel delegate, BSFormatter formatter) { public OffersViewModel(OffersDataModel dataModel, BSFormatter formatter) {
super(delegate); super(dataModel);
this.formatter = formatter; this.formatter = formatter;
} }
void removeOffer(OfferListItem item) { void removeOffer(OfferListItem item) {
delegate.removeOffer(item); dataModel.removeOffer(item);
} }
public ObservableList<OfferListItem> getList() { public ObservableList<OfferListItem> getList() {
return delegate.getList(); return dataModel.getList();
} }
String getTradeId(OfferListItem item) { String getTradeId(OfferListItem item) {
@ -65,7 +65,7 @@ class OffersViewModel extends ActivatableWithDelegate<OffersDataModel> implement
} }
String getDirectionLabel(OfferListItem item) { String getDirectionLabel(OfferListItem item) {
return (item != null) ? formatter.formatDirection(delegate.getDirection(item.getOffer())) : ""; return (item != null) ? formatter.formatDirection(dataModel.getDirection(item.getOffer())) : "";
} }
String getDate(OfferListItem item) { String getDate(OfferListItem item) {

View file

@ -31,7 +31,7 @@ import com.google.inject.Inject;
import java.util.Date; import java.util.Date;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.InvalidationListener; import javafx.beans.InvalidationListener;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
@ -45,7 +45,7 @@ import javafx.collections.ObservableList;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataModel> implements ViewModel { class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataModel> implements ViewModel {
private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class); private static final Logger log = LoggerFactory.getLogger(PendingTradesViewModel.class);
enum State { enum State {
@ -71,9 +71,9 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
@Inject @Inject
public PendingTradesViewModel(PendingTradesDataModel delegate, BSFormatter formatter, public PendingTradesViewModel(PendingTradesDataModel dataModel, BSFormatter formatter,
BtcAddressValidator btcAddressValidator) { BtcAddressValidator btcAddressValidator) {
super(delegate); super(dataModel);
this.formatter = formatter; this.formatter = formatter;
this.btcAddressValidator = btcAddressValidator; this.btcAddressValidator = btcAddressValidator;
@ -82,10 +82,10 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
@Override @Override
public void doActivate() { public void doActivate() {
txId.bind(delegate.txId); txId.bind(dataModel.txId);
fault.bind(delegate.fault); fault.bind(dataModel.fault);
delegate.tradeState.addListener(stateChangeListener); dataModel.tradeState.addListener(stateChangeListener);
updateState(); updateState();
} }
@ -94,25 +94,25 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
txId.unbind(); txId.unbind();
fault.unbind(); fault.unbind();
delegate.tradeState.removeListener(stateChangeListener); dataModel.tradeState.removeListener(stateChangeListener);
} }
void selectTrade(PendingTradesListItem item) { void selectTrade(PendingTradesListItem item) {
delegate.selectTrade(item); dataModel.selectTrade(item);
updateState(); updateState();
} }
void fiatPaymentStarted() { void fiatPaymentStarted() {
delegate.fiatPaymentStarted(); dataModel.fiatPaymentStarted();
} }
void fiatPaymentReceived() { void fiatPaymentReceived() {
delegate.fiatPaymentReceived(); dataModel.fiatPaymentReceived();
} }
void withdraw(String withdrawToAddress) { void withdraw(String withdrawToAddress) {
delegate.withdraw(withdrawToAddress); dataModel.withdraw(withdrawToAddress);
} }
void withdrawAddressFocusOut(String text) { void withdrawAddressFocusOut(String text) {
@ -120,27 +120,27 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
} }
String getAmountToWithdraw() { String getAmountToWithdraw() {
return formatter.formatCoinWithCode(delegate.getAmountToWithdraw()); //.subtract(FeePolicy.TX_FEE)); return formatter.formatCoinWithCode(dataModel.getAmountToWithdraw()); //.subtract(FeePolicy.TX_FEE));
} }
ObservableList<PendingTradesListItem> getList() { ObservableList<PendingTradesListItem> getList() {
return delegate.getList(); return dataModel.getList();
} }
boolean isOfferer() { boolean isOfferer() {
return delegate.isOfferer(); return dataModel.isOfferer();
} }
WalletService getWalletService() { WalletService getWalletService() {
return delegate.getWalletService(); return dataModel.getWalletService();
} }
PendingTradesListItem getSelectedItem() { PendingTradesListItem getSelectedItem() {
return delegate.getSelectedItem(); return dataModel.getSelectedItem();
} }
String getCurrencyCode() { String getCurrencyCode() {
return delegate.getCurrencyCode(); return dataModel.getCurrencyCode();
} }
// columns // columns
@ -161,7 +161,7 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
} }
String evaluateDirection(PendingTradesListItem item) { String evaluateDirection(PendingTradesListItem item) {
return (item != null) ? formatter.formatDirection(delegate.getDirection(item.getTrade().getOffer())) : ""; return (item != null) ? formatter.formatDirection(dataModel.getDirection(item.getTrade().getOffer())) : "";
} }
String formatDate(Date value) { String formatDate(Date value) {
@ -170,45 +170,45 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
// payment // payment
String getPaymentMethod() { String getPaymentMethod() {
return BSResources.get(delegate.getTrade().getContract().getTakerBankAccount().getBankAccountType().toString()); return BSResources.get(dataModel.getTrade().getContract().getTakerBankAccount().getBankAccountType().toString());
} }
String getFiatAmount() { String getFiatAmount() {
return formatter.formatFiatWithCode(delegate.getTrade().getTradeVolume()); return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
} }
String getHolderName() { String getHolderName() {
return delegate.getTrade().getContract().getTakerBankAccount().getAccountHolderName(); return dataModel.getTrade().getContract().getTakerBankAccount().getAccountHolderName();
} }
String getPrimaryId() { String getPrimaryId() {
return delegate.getTrade().getContract().getTakerBankAccount().getAccountPrimaryID(); return dataModel.getTrade().getContract().getTakerBankAccount().getAccountPrimaryID();
} }
String getSecondaryId() { String getSecondaryId() {
return delegate.getTrade().getContract().getTakerBankAccount().getAccountSecondaryID(); return dataModel.getTrade().getContract().getTakerBankAccount().getAccountSecondaryID();
} }
// summary // summary
String getTradeVolume() { String getTradeVolume() {
return formatter.formatCoinWithCode(delegate.getTrade().getTradeAmount()); return formatter.formatCoinWithCode(dataModel.getTrade().getTradeAmount());
} }
String getFiatVolume() { String getFiatVolume() {
return formatter.formatFiatWithCode(delegate.getTrade().getTradeVolume()); return formatter.formatFiatWithCode(dataModel.getTrade().getTradeVolume());
} }
String getTotalFees() { String getTotalFees() {
return formatter.formatCoinWithCode(delegate.getTotalFees()); return formatter.formatCoinWithCode(dataModel.getTotalFees());
} }
String getSecurityDeposit() { String getSecurityDeposit() {
// securityDeposit is handled different for offerer and taker. // securityDeposit is handled different for offerer and taker.
// Offerer have paid in the max amount, but taker might have taken less so also paid in less securityDeposit // Offerer have paid in the max amount, but taker might have taken less so also paid in less securityDeposit
if (delegate.isOfferer()) if (dataModel.isOfferer())
return formatter.formatCoinWithCode(delegate.getTrade().getOffer().getSecurityDeposit()); return formatter.formatCoinWithCode(dataModel.getTrade().getOffer().getSecurityDeposit());
else else
return formatter.formatCoinWithCode(delegate.getTrade().getSecurityDeposit()); return formatter.formatCoinWithCode(dataModel.getTrade().getSecurityDeposit());
} }
BtcAddressValidator getBtcAddressValidator() { BtcAddressValidator getBtcAddressValidator() {
@ -217,25 +217,25 @@ class PendingTradesViewModel extends ActivatableWithDelegate<PendingTradesDataMo
private void updateState() { private void updateState() {
Trade.State tradeState = delegate.tradeState.get(); Trade.State tradeState = dataModel.tradeState.get();
log.trace("tradeState " + tradeState); log.trace("tradeState " + tradeState);
if (tradeState != null) { if (tradeState != null) {
switch (tradeState) { switch (tradeState) {
// TODO Check why OFFERER_ACCEPTED can happen, refactor state handling // TODO Check why OFFERER_ACCEPTED can happen, refactor state handling
case OFFERER_ACCEPTED: case OFFERER_ACCEPTED:
case DEPOSIT_PUBLISHED: case DEPOSIT_PUBLISHED:
state.set(delegate.isOfferer() ? State.OFFERER_BUYER_WAIT_TX_CONF : State.TAKER_SELLER_WAIT_TX_CONF); state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_WAIT_TX_CONF : State.TAKER_SELLER_WAIT_TX_CONF);
break; break;
case DEPOSIT_CONFIRMED: case DEPOSIT_CONFIRMED:
state.set(delegate.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT : state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_START_PAYMENT :
State.TAKER_SELLER_WAIT_PAYMENT_STARTED); State.TAKER_SELLER_WAIT_PAYMENT_STARTED);
break; break;
case PAYMENT_STARTED: case PAYMENT_STARTED:
state.set(delegate.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED : state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_WAIT_CONFIRM_PAYMENT_RECEIVED :
State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT); State.TAKER_SELLER_CONFIRM_RECEIVE_PAYMENT);
break; break;
case COMPLETED: case COMPLETED:
state.set(delegate.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED); state.set(dataModel.isOfferer() ? State.OFFERER_BUYER_COMPLETED : State.TAKER_SELLER_COMPLETED);
break; break;
case FAILED: case FAILED:
// TODO error states not implemented yet // TODO error states not implemented yet

View file

@ -20,33 +20,33 @@ package io.bitsquare.gui.main.settings.application;
import com.google.inject.Inject; import com.google.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
class PreferencesViewModel extends ActivatableWithDelegate<PreferencesDataModel> implements ViewModel { class PreferencesViewModel extends ActivatableWithDataModel<PreferencesDataModel> implements ViewModel {
@Inject @Inject
public PreferencesViewModel(PreferencesDataModel delegate) { public PreferencesViewModel(PreferencesDataModel dataModel) {
super(delegate); super(dataModel);
} }
public ObservableList<String> getBtcDenominationItems() { public ObservableList<String> getBtcDenominationItems() {
return delegate.btcDenominations; return dataModel.btcDenominations;
} }
BooleanProperty useAnimations() { BooleanProperty useAnimations() {
return delegate.useAnimations; return dataModel.useAnimations;
} }
BooleanProperty useEffects() { BooleanProperty useEffects() {
return delegate.useEffects; return dataModel.useEffects;
} }
StringProperty btcDenomination() { StringProperty btcDenomination() {
return delegate.btcDenomination; return dataModel.btcDenomination;
} }

View file

@ -32,7 +32,7 @@ import org.bitcoinj.utils.Fiat;
import javax.inject.Inject; import javax.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
@ -45,7 +45,7 @@ import javafx.beans.property.StringProperty;
import static javafx.beans.binding.Bindings.createStringBinding; import static javafx.beans.binding.Bindings.createStringBinding;
class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel> implements ViewModel { class CreateOfferViewModel extends ActivatableWithDataModel<CreateOfferDataModel> implements ViewModel {
private final BtcValidator btcValidator; private final BtcValidator btcValidator;
private final BSFormatter formatter; private final BSFormatter formatter;
@ -94,19 +94,19 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
@Inject @Inject
public CreateOfferViewModel(CreateOfferDataModel delegate, FiatValidator fiatValidator, BtcValidator btcValidator, public CreateOfferViewModel(CreateOfferDataModel dataModel, FiatValidator fiatValidator, BtcValidator btcValidator,
BSFormatter formatter) { BSFormatter formatter) {
super(delegate); super(dataModel);
this.fiatValidator = fiatValidator; this.fiatValidator = fiatValidator;
this.btcValidator = btcValidator; this.btcValidator = btcValidator;
this.formatter = formatter; this.formatter = formatter;
paymentLabel.set(BSResources.get("createOffer.fundsBox.paymentLabel", delegate.getOfferId())); paymentLabel.set(BSResources.get("createOffer.fundsBox.paymentLabel", dataModel.getOfferId()));
if (delegate.getAddressEntry() != null) { if (dataModel.getAddressEntry() != null) {
addressAsString.set(delegate.getAddressEntry().getAddress().toString()); addressAsString.set(dataModel.getAddressEntry().getAddress().toString());
address.set(delegate.getAddressEntry().getAddress()); address.set(dataModel.getAddressEntry().getAddress());
} }
setupBindings(); setupBindings();
@ -115,39 +115,39 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
// setOfferBookFilter is a one time call // setOfferBookFilter is a one time call
void initWithData(Direction direction, Coin amount, Fiat price) { void initWithData(Direction direction, Coin amount, Fiat price) {
delegate.setDirection(direction); dataModel.setDirection(direction);
directionLabel.set(delegate.getDirection() == Direction.BUY ? BSResources.get("shared.buy") : BSResources.get directionLabel.set(dataModel.getDirection() == Direction.BUY ? BSResources.get("shared.buy") : BSResources.get
("shared.sell")); ("shared.sell"));
// apply only if valid // apply only if valid
boolean amountValid = false; boolean amountValid = false;
if (amount != null && isBtcInputValid(amount.toPlainString()) if (amount != null && isBtcInputValid(amount.toPlainString())
.isValid) { .isValid) {
delegate.amountAsCoin.set(amount); dataModel.amountAsCoin.set(amount);
delegate.minAmountAsCoin.set(amount); dataModel.minAmountAsCoin.set(amount);
amountValid = true; amountValid = true;
} }
// apply only if valid // apply only if valid
boolean priceValid = false; boolean priceValid = false;
if (price != null && isBtcInputValid(price.toPlainString()).isValid) { if (price != null && isBtcInputValid(price.toPlainString()).isValid) {
delegate.priceAsFiat.set(formatter.parseToFiatWith2Decimals(price.toPlainString())); dataModel.priceAsFiat.set(formatter.parseToFiatWith2Decimals(price.toPlainString()));
priceValid = true; priceValid = true;
} }
if (amountValid && priceValid) if (amountValid && priceValid)
delegate.calculateTotalToPay(); dataModel.calculateTotalToPay();
} }
void placeOffer() { void placeOffer() {
delegate.requestPlaceOfferErrorMessage.set(null); dataModel.requestPlaceOfferErrorMessage.set(null);
delegate.requestPlaceOfferSuccess.set(false); dataModel.requestPlaceOfferSuccess.set(false);
isPlaceOfferButtonDisabled.set(true); isPlaceOfferButtonDisabled.set(true);
isPlaceOfferSpinnerVisible.set(true); isPlaceOfferSpinnerVisible.set(true);
delegate.placeOffer(); dataModel.placeOffer();
} }
@ -165,12 +165,12 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
// only allow max 4 decimal places for btc values // only allow max 4 decimal places for btc values
setAmountToModel(); setAmountToModel();
// reformat input // reformat input
amount.set(formatter.formatCoin(delegate.amountAsCoin.get())); amount.set(formatter.formatCoin(dataModel.amountAsCoin.get()));
calculateVolume(); calculateVolume();
// handle minAmount/amount relationship // handle minAmount/amount relationship
if (!delegate.isMinAmountLessOrEqualAmount()) { if (!dataModel.isMinAmountLessOrEqualAmount()) {
amountValidationResult.set(new InputValidator.ValidationResult(false, amountValidationResult.set(new InputValidator.ValidationResult(false,
BSResources.get("createOffer.validation.amountSmallerThanMinAmount"))); BSResources.get("createOffer.validation.amountSmallerThanMinAmount")));
} }
@ -190,9 +190,9 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
if (result.isValid) { if (result.isValid) {
showWarningInvalidBtcDecimalPlaces.set(!formatter.hasBtcValidDecimals(userInput)); showWarningInvalidBtcDecimalPlaces.set(!formatter.hasBtcValidDecimals(userInput));
setMinAmountToModel(); setMinAmountToModel();
minAmount.set(formatter.formatCoin(delegate.minAmountAsCoin.get())); minAmount.set(formatter.formatCoin(dataModel.minAmountAsCoin.get()));
if (!delegate.isMinAmountLessOrEqualAmount()) { if (!dataModel.isMinAmountLessOrEqualAmount()) {
minAmountValidationResult.set(new InputValidator.ValidationResult(false, minAmountValidationResult.set(new InputValidator.ValidationResult(false,
BSResources.get("createOffer.validation.minAmountLargerThanAmount"))); BSResources.get("createOffer.validation.minAmountLargerThanAmount")));
} }
@ -213,7 +213,7 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
if (isValid) { if (isValid) {
showWarningInvalidFiatDecimalPlaces.set(!formatter.hasFiatValidDecimals(userInput)); showWarningInvalidFiatDecimalPlaces.set(!formatter.hasFiatValidDecimals(userInput));
setPriceToModel(); setPriceToModel();
price.set(formatter.formatFiat(delegate.priceAsFiat.get())); price.set(formatter.formatFiat(dataModel.priceAsFiat.get()));
calculateVolume(); calculateVolume();
} }
@ -227,7 +227,7 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
if (result.isValid) { if (result.isValid) {
showWarningInvalidFiatDecimalPlaces.set(!formatter.hasFiatValidDecimals(userInput)); showWarningInvalidFiatDecimalPlaces.set(!formatter.hasFiatValidDecimals(userInput));
setVolumeToModel(); setVolumeToModel();
volume.set(formatter.formatFiat(delegate.volumeAsFiat.get())); volume.set(formatter.formatFiat(dataModel.volumeAsFiat.get()));
calculateAmount(); calculateAmount();
@ -241,12 +241,12 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
} }
void securityDepositInfoDisplayed() { void securityDepositInfoDisplayed() {
delegate.securityDepositInfoDisplayed(); dataModel.securityDepositInfoDisplayed();
} }
WalletService getWalletService() { WalletService getWalletService() {
return delegate.getWalletService(); return dataModel.getWalletService();
} }
BSFormatter getFormatter() { BSFormatter getFormatter() {
@ -254,7 +254,7 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
} }
Boolean displaySecurityDepositInfo() { Boolean displaySecurityDepositInfo() {
return delegate.displaySecurityDepositInfo(); return dataModel.displaySecurityDepositInfo();
} }
private void setupListeners() { private void setupListeners() {
@ -264,7 +264,7 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
if (isBtcInputValid(newValue).isValid) { if (isBtcInputValid(newValue).isValid) {
setAmountToModel(); setAmountToModel();
calculateVolume(); calculateVolume();
delegate.calculateTotalToPay(); dataModel.calculateTotalToPay();
} }
updateButtonDisableState(); updateButtonDisableState();
}); });
@ -278,7 +278,7 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
if (isFiatInputValid(newValue).isValid) { if (isFiatInputValid(newValue).isValid) {
setPriceToModel(); setPriceToModel();
calculateVolume(); calculateVolume();
delegate.calculateTotalToPay(); dataModel.calculateTotalToPay();
} }
updateButtonDisableState(); updateButtonDisableState();
}); });
@ -287,12 +287,12 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
if (isFiatInputValid(newValue).isValid) { if (isFiatInputValid(newValue).isValid) {
setVolumeToModel(); setVolumeToModel();
setPriceToModel(); setPriceToModel();
delegate.calculateAmount(); dataModel.calculateAmount();
delegate.calculateTotalToPay(); dataModel.calculateTotalToPay();
} }
updateButtonDisableState(); updateButtonDisableState();
}); });
delegate.isWalletFunded.addListener((ov, oldValue, newValue) -> { dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue) { if (newValue) {
updateButtonDisableState(); updateButtonDisableState();
tabIsClosable.set(false); tabIsClosable.set(false);
@ -300,70 +300,70 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
}); });
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding // Binding with Bindings.createObjectBinding does not work because of bi-directional binding
delegate.amountAsCoin.addListener((ov, oldValue, newValue) -> amount.set(formatter.formatCoin(newValue))); dataModel.amountAsCoin.addListener((ov, oldValue, newValue) -> amount.set(formatter.formatCoin(newValue)));
delegate.minAmountAsCoin.addListener((ov, oldValue, newValue) -> minAmount.set(formatter.formatCoin(newValue))); dataModel.minAmountAsCoin.addListener((ov, oldValue, newValue) -> minAmount.set(formatter.formatCoin(newValue)));
delegate.priceAsFiat.addListener((ov, oldValue, newValue) -> price.set(formatter.formatFiat(newValue))); dataModel.priceAsFiat.addListener((ov, oldValue, newValue) -> price.set(formatter.formatFiat(newValue)));
delegate.volumeAsFiat.addListener((ov, oldValue, newValue) -> volume.set(formatter.formatFiat(newValue))); dataModel.volumeAsFiat.addListener((ov, oldValue, newValue) -> volume.set(formatter.formatFiat(newValue)));
delegate.requestPlaceOfferErrorMessage.addListener((ov, oldValue, newValue) -> { dataModel.requestPlaceOfferErrorMessage.addListener((ov, oldValue, newValue) -> {
if (newValue != null) { if (newValue != null) {
isPlaceOfferButtonDisabled.set(false); isPlaceOfferButtonDisabled.set(false);
isPlaceOfferSpinnerVisible.set(false); isPlaceOfferSpinnerVisible.set(false);
} }
}); });
delegate.requestPlaceOfferSuccess.addListener((ov, oldValue, newValue) -> { dataModel.requestPlaceOfferSuccess.addListener((ov, oldValue, newValue) -> {
isPlaceOfferButtonVisible.set(!newValue); isPlaceOfferButtonVisible.set(!newValue);
isPlaceOfferSpinnerVisible.set(false); isPlaceOfferSpinnerVisible.set(false);
}); });
// ObservableLists // ObservableLists
delegate.acceptedCountries.addListener((Observable o) -> acceptedCountries.set(formatter dataModel.acceptedCountries.addListener((Observable o) -> acceptedCountries.set(formatter
.countryLocalesToString(delegate.acceptedCountries))); .countryLocalesToString(dataModel.acceptedCountries)));
delegate.acceptedLanguages.addListener((Observable o) -> acceptedLanguages.set(formatter dataModel.acceptedLanguages.addListener((Observable o) -> acceptedLanguages.set(formatter
.languageLocalesToString(delegate.acceptedLanguages))); .languageLocalesToString(dataModel.acceptedLanguages)));
delegate.acceptedArbitrators.addListener((Observable o) -> acceptedArbitrators.set(formatter dataModel.acceptedArbitrators.addListener((Observable o) -> acceptedArbitrators.set(formatter
.arbitratorsToString(delegate.acceptedArbitrators))); .arbitratorsToString(dataModel.acceptedArbitrators)));
} }
private void setupBindings() { private void setupBindings() {
totalToPay.bind(createStringBinding(() -> formatter.formatCoinWithCode(delegate.totalToPayAsCoin.get()), totalToPay.bind(createStringBinding(() -> formatter.formatCoinWithCode(dataModel.totalToPayAsCoin.get()),
delegate.totalToPayAsCoin)); dataModel.totalToPayAsCoin));
securityDeposit.bind(createStringBinding(() -> formatter.formatCoinWithCode(delegate.securityDepositAsCoin.get()), securityDeposit.bind(createStringBinding(() -> formatter.formatCoinWithCode(dataModel.securityDepositAsCoin.get()),
delegate.securityDepositAsCoin)); dataModel.securityDepositAsCoin));
totalToPayAsCoin.bind(delegate.totalToPayAsCoin); totalToPayAsCoin.bind(dataModel.totalToPayAsCoin);
offerFee.bind(createStringBinding(() -> formatter.formatCoinWithCode(delegate.offerFeeAsCoin.get()), offerFee.bind(createStringBinding(() -> formatter.formatCoinWithCode(dataModel.offerFeeAsCoin.get()),
delegate.offerFeeAsCoin)); dataModel.offerFeeAsCoin));
networkFee.bind(createStringBinding(() -> formatter.formatCoinWithCode(delegate.networkFeeAsCoin.get()), networkFee.bind(createStringBinding(() -> formatter.formatCoinWithCode(dataModel.networkFeeAsCoin.get()),
delegate.offerFeeAsCoin)); dataModel.offerFeeAsCoin));
bankAccountType.bind(Bindings.createStringBinding(() -> BSResources.get(delegate.bankAccountType.get()), bankAccountType.bind(Bindings.createStringBinding(() -> BSResources.get(dataModel.bankAccountType.get()),
delegate.bankAccountType)); dataModel.bankAccountType));
bankAccountCurrency.bind(delegate.bankAccountCurrency); bankAccountCurrency.bind(dataModel.bankAccountCurrency);
bankAccountCounty.bind(delegate.bankAccountCounty); bankAccountCounty.bind(dataModel.bankAccountCounty);
requestPlaceOfferErrorMessage.bind(delegate.requestPlaceOfferErrorMessage); requestPlaceOfferErrorMessage.bind(dataModel.requestPlaceOfferErrorMessage);
showTransactionPublishedScreen.bind(delegate.requestPlaceOfferSuccess); showTransactionPublishedScreen.bind(dataModel.requestPlaceOfferSuccess);
transactionId.bind(delegate.transactionId); transactionId.bind(dataModel.transactionId);
btcCode.bind(delegate.btcCode); btcCode.bind(dataModel.btcCode);
fiatCode.bind(delegate.fiatCode); fiatCode.bind(dataModel.fiatCode);
} }
private void calculateVolume() { private void calculateVolume() {
setAmountToModel(); setAmountToModel();
setPriceToModel(); setPriceToModel();
delegate.calculateVolume(); dataModel.calculateVolume();
} }
private void calculateAmount() { private void calculateAmount() {
setVolumeToModel(); setVolumeToModel();
setPriceToModel(); setPriceToModel();
delegate.calculateAmount(); dataModel.calculateAmount();
// Amount calculation could lead to amount/minAmount invalidation // Amount calculation could lead to amount/minAmount invalidation
if (!delegate.isMinAmountLessOrEqualAmount()) { if (!dataModel.isMinAmountLessOrEqualAmount()) {
amountValidationResult.set(new InputValidator.ValidationResult(false, amountValidationResult.set(new InputValidator.ValidationResult(false,
BSResources.get("createOffer.validation.amountSmallerThanMinAmount"))); BSResources.get("createOffer.validation.amountSmallerThanMinAmount")));
} }
@ -376,19 +376,19 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
} }
private void setAmountToModel() { private void setAmountToModel() {
delegate.amountAsCoin.set(formatter.parseToCoinWith4Decimals(amount.get())); dataModel.amountAsCoin.set(formatter.parseToCoinWith4Decimals(amount.get()));
} }
private void setMinAmountToModel() { private void setMinAmountToModel() {
delegate.minAmountAsCoin.set(formatter.parseToCoinWith4Decimals(minAmount.get())); dataModel.minAmountAsCoin.set(formatter.parseToCoinWith4Decimals(minAmount.get()));
} }
private void setPriceToModel() { private void setPriceToModel() {
delegate.priceAsFiat.set(formatter.parseToFiatWith2Decimals(price.get())); dataModel.priceAsFiat.set(formatter.parseToFiatWith2Decimals(price.get()));
} }
private void setVolumeToModel() { private void setVolumeToModel() {
delegate.volumeAsFiat.set(formatter.parseToFiatWith2Decimals(volume.get())); dataModel.volumeAsFiat.set(formatter.parseToFiatWith2Decimals(volume.get()));
} }
private void updateButtonDisableState() { private void updateButtonDisableState() {
@ -396,8 +396,8 @@ class CreateOfferViewModel extends ActivatableWithDelegate<CreateOfferDataModel>
isBtcInputValid(minAmount.get()).isValid && isBtcInputValid(minAmount.get()).isValid &&
isBtcInputValid(price.get()).isValid && isBtcInputValid(price.get()).isValid &&
isBtcInputValid(volume.get()).isValid && isBtcInputValid(volume.get()).isValid &&
delegate.isMinAmountLessOrEqualAmount() && dataModel.isMinAmountLessOrEqualAmount() &&
delegate.isWalletFunded.get()) dataModel.isWalletFunded.get())
); );
} }

View file

@ -26,6 +26,8 @@ import io.bitsquare.offer.Offer;
import io.bitsquare.settings.Preferences; import io.bitsquare.settings.Preferences;
import io.bitsquare.trade.TradeManager; import io.bitsquare.trade.TradeManager;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.task.FaultHandler;
import io.bitsquare.util.task.ResultHandler;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.ExchangeRate; import org.bitcoinj.utils.ExchangeRate;
@ -114,8 +116,8 @@ class OfferBookDataModel implements Activatable, DataModel {
btcCode.unbind(); btcCode.unbind();
} }
void removeOffer(Offer offer) { void removeOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) {
tradeManager.removeOffer(offer); tradeManager.requestRemoveOffer(offer, resultHandler, faultHandler);
} }
void calculateVolume() { void calculateVolume() {

View file

@ -17,6 +17,7 @@
package io.bitsquare.gui.main.trade.offerbook; package io.bitsquare.gui.main.trade.offerbook;
import io.bitsquare.gui.components.Popups;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.gui.util.validation.InputValidator; import io.bitsquare.gui.util.validation.InputValidator;
import io.bitsquare.gui.util.validation.OptionalBtcValidator; import io.bitsquare.gui.util.validation.OptionalBtcValidator;
@ -31,13 +32,17 @@ import org.bitcoinj.utils.Fiat;
import com.google.inject.Inject; import com.google.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty; import javafx.beans.property.StringProperty;
import javafx.collections.transformation.SortedList; import javafx.collections.transformation.SortedList;
class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> implements ViewModel { import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class OfferBookViewModel extends ActivatableWithDataModel<OfferBookDataModel> implements ViewModel {
private static final Logger log = LoggerFactory.getLogger(OfferBookViewModel.class);
private final OptionalBtcValidator optionalBtcValidator; private final OptionalBtcValidator optionalBtcValidator;
private final BSFormatter formatter; private final BSFormatter formatter;
@ -52,17 +57,17 @@ class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> imp
@Inject @Inject
public OfferBookViewModel(OfferBookDataModel delegate, OptionalFiatValidator optionalFiatValidator, public OfferBookViewModel(OfferBookDataModel dataModel, OptionalFiatValidator optionalFiatValidator,
OptionalBtcValidator optionalBtcValidator, BSFormatter formatter) { OptionalBtcValidator optionalBtcValidator, BSFormatter formatter) {
super(delegate); super(dataModel);
this.optionalFiatValidator = optionalFiatValidator; this.optionalFiatValidator = optionalFiatValidator;
this.optionalBtcValidator = optionalBtcValidator; this.optionalBtcValidator = optionalBtcValidator;
this.formatter = formatter; this.formatter = formatter;
btcCode.bind(delegate.btcCode); btcCode.bind(dataModel.btcCode);
fiatCode.bind(delegate.fiatCode); fiatCode.bind(dataModel.fiatCode);
restrictionsInfo.bind(delegate.restrictionsInfo); restrictionsInfo.bind(dataModel.restrictionsInfo);
// Bidirectional bindings are used for all input fields: amount, price and volume // Bidirectional bindings are used for all input fields: amount, price and volume
// We do volume/amount calculation during input, so user has immediate feedback // We do volume/amount calculation during input, so user has immediate feedback
@ -70,7 +75,7 @@ class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> imp
if (isBtcInputValid(newValue).isValid) { if (isBtcInputValid(newValue).isValid) {
setAmountToModel(); setAmountToModel();
setPriceToModel(); setPriceToModel();
delegate.calculateVolume(); dataModel.calculateVolume();
} }
}); });
@ -78,7 +83,7 @@ class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> imp
if (isFiatInputValid(newValue).isValid) { if (isFiatInputValid(newValue).isValid) {
setAmountToModel(); setAmountToModel();
setPriceToModel(); setPriceToModel();
delegate.calculateVolume(); dataModel.calculateVolume();
} }
}); });
@ -86,42 +91,51 @@ class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> imp
if (isFiatInputValid(newValue).isValid) { if (isFiatInputValid(newValue).isValid) {
setPriceToModel(); setPriceToModel();
setVolumeToModel(); setVolumeToModel();
delegate.calculateAmount(); dataModel.calculateAmount();
} }
}); });
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding // Binding with Bindings.createObjectBinding does not work because of bi-directional binding
delegate.amountAsCoinProperty().addListener((ov, oldValue, newValue) -> amount.set(formatter.formatCoin dataModel.amountAsCoinProperty().addListener((ov, oldValue, newValue) -> amount.set(formatter.formatCoin
(newValue))); (newValue)));
delegate.priceAsFiatProperty().addListener((ov, oldValue, newValue) -> price.set(formatter.formatFiat(newValue))); dataModel.priceAsFiatProperty().addListener((ov, oldValue, newValue) -> price.set(formatter.formatFiat(newValue)));
delegate.volumeAsFiatProperty().addListener((ov, oldValue, newValue) -> volume.set(formatter.formatFiat dataModel.volumeAsFiatProperty().addListener((ov, oldValue, newValue) -> volume.set(formatter.formatFiat
(newValue))); (newValue)));
} }
void removeOffer(Offer offer) { void removeOffer(Offer offer) {
delegate.removeOffer(offer); dataModel.removeOffer(offer,
() -> {
// visual feedback?
log.debug("remove was successful");
},
(message, throwable) -> {
log.error(message);
Popups.openWarningPopup("Remove offer failed", message);
}
);
} }
boolean isTradable(Offer offer) { boolean isTradable(Offer offer) {
return delegate.isTradable(offer); return dataModel.isTradable(offer);
} }
void setDirection(Direction direction) { void setDirection(Direction direction) {
delegate.setDirection(direction); dataModel.setDirection(direction);
} }
SortedList<OfferBookListItem> getOfferList() { SortedList<OfferBookListItem> getOfferList() {
return delegate.getOfferList(); return dataModel.getOfferList();
} }
boolean isRegistered() { boolean isRegistered() {
return delegate.isRegistered(); return dataModel.isRegistered();
} }
boolean isMyOffer(Offer offer) { boolean isMyOffer(Offer offer) {
return delegate.isMyOffer(offer); return dataModel.isMyOffer(offer);
} }
String getAmount(OfferBookListItem item) { String getAmount(OfferBookListItem item) {
@ -147,15 +161,15 @@ class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> imp
} }
Direction getDirection() { Direction getDirection() {
return delegate.getDirection(); return dataModel.getDirection();
} }
Coin getAmountAsCoin() { Coin getAmountAsCoin() {
return delegate.getAmountAsCoin(); return dataModel.getAmountAsCoin();
} }
Fiat getPriceAsCoin() { Fiat getPriceAsCoin() {
return delegate.getPriceAsFiat(); return dataModel.getPriceAsFiat();
} }
private InputValidator.ValidationResult isBtcInputValid(String input) { private InputValidator.ValidationResult isBtcInputValid(String input) {
@ -167,15 +181,15 @@ class OfferBookViewModel extends ActivatableWithDelegate<OfferBookDataModel> imp
} }
private void setAmountToModel() { private void setAmountToModel() {
delegate.setAmount(formatter.parseToCoinWith4Decimals(amount.get())); dataModel.setAmount(formatter.parseToCoinWith4Decimals(amount.get()));
} }
private void setPriceToModel() { private void setPriceToModel() {
delegate.setPrice(formatter.parseToFiatWith2Decimals(price.get())); dataModel.setPrice(formatter.parseToFiatWith2Decimals(price.get()));
} }
private void setVolumeToModel() { private void setVolumeToModel() {
delegate.setVolume(formatter.parseToFiatWith2Decimals(volume.get())); dataModel.setVolume(formatter.parseToFiatWith2Decimals(volume.get()));
} }
} }

View file

@ -31,7 +31,7 @@ import org.bitcoinj.core.Coin;
import javax.inject.Inject; import javax.inject.Inject;
import viewfx.model.ViewModel; import viewfx.model.ViewModel;
import viewfx.model.support.ActivatableWithDelegate; import viewfx.model.support.ActivatableWithDataModel;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -42,7 +42,7 @@ import javafx.beans.property.StringProperty;
import static javafx.beans.binding.Bindings.createStringBinding; import static javafx.beans.binding.Bindings.createStringBinding;
class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> implements ViewModel { class TakeOfferViewModel extends ActivatableWithDataModel<TakeOfferDataModel> implements ViewModel {
private String fiatCode; private String fiatCode;
private String amountRange; private String amountRange;
@ -92,14 +92,14 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
@Inject @Inject
public TakeOfferViewModel(TakeOfferDataModel delegate, BtcValidator btcValidator, BSFormatter formatter) { public TakeOfferViewModel(TakeOfferDataModel dataModel, BtcValidator btcValidator, BSFormatter formatter) {
super(delegate); super(dataModel);
this.btcValidator = btcValidator; this.btcValidator = btcValidator;
this.formatter = formatter; this.formatter = formatter;
this.offerFee = formatter.formatCoinWithCode(delegate.offerFeeAsCoin.get()); this.offerFee = formatter.formatCoinWithCode(dataModel.offerFeeAsCoin.get());
this.networkFee = formatter.formatCoinWithCode(delegate.networkFeeAsCoin.get()); this.networkFee = formatter.formatCoinWithCode(dataModel.networkFeeAsCoin.get());
setupBindings(); setupBindings();
setupListeners(); setupListeners();
@ -107,13 +107,13 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
// setOfferBookFilter is a one time call // setOfferBookFilter is a one time call
void initWithData(Direction direction, Coin amount, Offer offer) { void initWithData(Direction direction, Coin amount, Offer offer) {
delegate.initWithData(amount, offer); dataModel.initWithData(amount, offer);
directionLabel = direction == Direction.BUY ? directionLabel = direction == Direction.BUY ?
BSResources.get("shared.buy") : BSResources.get("shared.sell"); BSResources.get("shared.buy") : BSResources.get("shared.sell");
fiatCode = offer.getCurrency().getCurrencyCode(); fiatCode = offer.getCurrency().getCurrencyCode();
if (!delegate.isMinAmountLessOrEqualAmount()) { if (!dataModel.isMinAmountLessOrEqualAmount()) {
amountValidationResult.set(new InputValidator.ValidationResult(false, amountValidationResult.set(new InputValidator.ValidationResult(false,
BSResources.get("takeOffer.validation.amountSmallerThanMinAmount"))); BSResources.get("takeOffer.validation.amountSmallerThanMinAmount")));
} }
@ -127,9 +127,9 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
price = formatter.formatFiatWithCode(offer.getPrice()); price = formatter.formatFiatWithCode(offer.getPrice());
paymentLabel = BSResources.get("takeOffer.fundsBox.paymentLabel", offer.getId()); paymentLabel = BSResources.get("takeOffer.fundsBox.paymentLabel", offer.getId());
if (delegate.getAddressEntry() != null) { if (dataModel.getAddressEntry() != null) {
addressAsString = delegate.getAddressEntry().getAddress().toString(); addressAsString = dataModel.getAddressEntry().getAddress().toString();
address.set(delegate.getAddressEntry().getAddress()); address.set(dataModel.getAddressEntry().getAddress());
} }
acceptedCountries = formatter.countryLocalesToString(offer.getAcceptedCountries()); acceptedCountries = formatter.countryLocalesToString(offer.getAcceptedCountries());
@ -141,17 +141,17 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
} }
void takeOffer() { void takeOffer() {
delegate.requestTakeOfferErrorMessage.set(null); dataModel.requestTakeOfferErrorMessage.set(null);
delegate.requestTakeOfferSuccess.set(false); dataModel.requestTakeOfferSuccess.set(false);
isTakeOfferButtonDisabled.set(true); isTakeOfferButtonDisabled.set(true);
isTakeOfferSpinnerVisible.set(true); isTakeOfferSpinnerVisible.set(true);
delegate.takeOffer(); dataModel.takeOffer();
} }
void securityDepositInfoDisplayed() { void securityDepositInfoDisplayed() {
delegate.securityDepositInfoDisplayed(); dataModel.securityDepositInfoDisplayed();
} }
@ -169,15 +169,15 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
// only allow max 4 decimal places for btc values // only allow max 4 decimal places for btc values
setAmountToModel(); setAmountToModel();
// reformat input // reformat input
amount.set(formatter.formatCoin(delegate.amountAsCoin.get())); amount.set(formatter.formatCoin(dataModel.amountAsCoin.get()));
calculateVolume(); calculateVolume();
if (!delegate.isMinAmountLessOrEqualAmount()) if (!dataModel.isMinAmountLessOrEqualAmount())
amountValidationResult.set(new InputValidator.ValidationResult(false, amountValidationResult.set(new InputValidator.ValidationResult(false,
BSResources.get("takeOffer.validation.amountSmallerThanMinAmount"))); BSResources.get("takeOffer.validation.amountSmallerThanMinAmount")));
if (delegate.isAmountLargerThanOfferAmount()) if (dataModel.isAmountLargerThanOfferAmount())
amountValidationResult.set(new InputValidator.ValidationResult(false, amountValidationResult.set(new InputValidator.ValidationResult(false,
BSResources.get("takeOffer.validation.amountLargerThanOfferAmount"))); BSResources.get("takeOffer.validation.amountLargerThanOfferAmount")));
} }
@ -186,7 +186,7 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
WalletService getWalletService() { WalletService getWalletService() {
return delegate.getWalletService(); return dataModel.getWalletService();
} }
BSFormatter getFormatter() { BSFormatter getFormatter() {
@ -206,7 +206,7 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
} }
String getAmount() { String getAmount() {
return formatter.formatCoinWithCode(delegate.amountAsCoin.get()); return formatter.formatCoinWithCode(dataModel.amountAsCoin.get());
} }
String getAmountRange() { String getAmountRange() {
@ -254,7 +254,7 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
} }
Boolean displaySecurityDepositInfo() { Boolean displaySecurityDepositInfo() {
return delegate.displaySecurityDepositInfo(); return dataModel.displaySecurityDepositInfo();
} }
@ -265,12 +265,12 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
if (isBtcInputValid(newValue).isValid) { if (isBtcInputValid(newValue).isValid) {
setAmountToModel(); setAmountToModel();
calculateVolume(); calculateVolume();
delegate.calculateTotalToPay(); dataModel.calculateTotalToPay();
} }
updateButtonDisableState(); updateButtonDisableState();
}); });
delegate.isWalletFunded.addListener((ov, oldValue, newValue) -> { dataModel.isWalletFunded.addListener((ov, oldValue, newValue) -> {
if (newValue) { if (newValue) {
updateButtonDisableState(); updateButtonDisableState();
tabIsClosable.set(false); tabIsClosable.set(false);
@ -278,53 +278,53 @@ class TakeOfferViewModel extends ActivatableWithDelegate<TakeOfferDataModel> imp
}); });
// Binding with Bindings.createObjectBinding does not work because of bi-directional binding // Binding with Bindings.createObjectBinding does not work because of bi-directional binding
delegate.amountAsCoin.addListener((ov, oldValue, newValue) -> amount.set(formatter.formatCoin(newValue))); dataModel.amountAsCoin.addListener((ov, oldValue, newValue) -> amount.set(formatter.formatCoin(newValue)));
delegate.requestTakeOfferErrorMessage.addListener((ov, oldValue, newValue) -> { dataModel.requestTakeOfferErrorMessage.addListener((ov, oldValue, newValue) -> {
if (newValue != null) { if (newValue != null) {
isTakeOfferButtonDisabled.set(false); isTakeOfferButtonDisabled.set(false);
isTakeOfferSpinnerVisible.set(false); isTakeOfferSpinnerVisible.set(false);
} }
}); });
delegate.requestTakeOfferSuccess.addListener((ov, oldValue, newValue) -> { dataModel.requestTakeOfferSuccess.addListener((ov, oldValue, newValue) -> {
isTakeOfferButtonVisible.set(!newValue); isTakeOfferButtonVisible.set(!newValue);
isTakeOfferSpinnerVisible.set(false); isTakeOfferSpinnerVisible.set(false);
}); });
} }
private void setupBindings() { private void setupBindings() {
volume.bind(createStringBinding(() -> formatter.formatFiatWithCode(delegate.volumeAsFiat.get()), volume.bind(createStringBinding(() -> formatter.formatFiatWithCode(dataModel.volumeAsFiat.get()),
delegate.volumeAsFiat)); dataModel.volumeAsFiat));
totalToPay.bind(createStringBinding(() -> formatter.formatCoinWithCode(delegate.totalToPayAsCoin.get()), totalToPay.bind(createStringBinding(() -> formatter.formatCoinWithCode(dataModel.totalToPayAsCoin.get()),
delegate.totalToPayAsCoin)); dataModel.totalToPayAsCoin));
securityDeposit.bind(createStringBinding(() -> formatter.formatCoinWithCode(delegate.securityDepositAsCoin securityDeposit.bind(createStringBinding(() -> formatter.formatCoinWithCode(dataModel.securityDepositAsCoin
.get()), .get()),
delegate.securityDepositAsCoin)); dataModel.securityDepositAsCoin));
totalToPayAsCoin.bind(delegate.totalToPayAsCoin); totalToPayAsCoin.bind(dataModel.totalToPayAsCoin);
requestTakeOfferErrorMessage.bind(delegate.requestTakeOfferErrorMessage); requestTakeOfferErrorMessage.bind(dataModel.requestTakeOfferErrorMessage);
showTransactionPublishedScreen.bind(delegate.requestTakeOfferSuccess); showTransactionPublishedScreen.bind(dataModel.requestTakeOfferSuccess);
transactionId.bind(delegate.transactionId); transactionId.bind(dataModel.transactionId);
offerIsAvailable.bind(delegate.offerIsAvailable); offerIsAvailable.bind(dataModel.offerIsAvailable);
btcCode.bind(delegate.btcCode); btcCode.bind(dataModel.btcCode);
} }
private void calculateVolume() { private void calculateVolume() {
setAmountToModel(); setAmountToModel();
delegate.calculateVolume(); dataModel.calculateVolume();
} }
private void setAmountToModel() { private void setAmountToModel() {
delegate.amountAsCoin.set(formatter.parseToCoinWith4Decimals(amount.get())); dataModel.amountAsCoin.set(formatter.parseToCoinWith4Decimals(amount.get()));
} }
private void updateButtonDisableState() { private void updateButtonDisableState() {
isTakeOfferButtonDisabled.set(!(isBtcInputValid(amount.get()).isValid && isTakeOfferButtonDisabled.set(!(isBtcInputValid(amount.get()).isValid &&
delegate.isMinAmountLessOrEqualAmount() && dataModel.isMinAmountLessOrEqualAmount() &&
!delegate.isAmountLargerThanOfferAmount() && !dataModel.isAmountLargerThanOfferAmount() &&
delegate.isWalletFunded.get()) dataModel.isWalletFunded.get())
); );
} }

View file

@ -64,6 +64,7 @@ public class Offer implements Serializable {
private final List<Locale> acceptedLanguageLocales; private final List<Locale> acceptedLanguageLocales;
private final String bankAccountUID; private final String bankAccountUID;
private final List<Arbitrator> arbitrators; private final List<Arbitrator> arbitrators;
private String offerFeePaymentTxID; private String offerFeePaymentTxID;

View file

@ -33,7 +33,7 @@ public interface RemoteOfferBook {
void addOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler); void addOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler);
void removeOffer(Offer offer); void removeOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler);
void addListener(Listener listener); void addListener(Listener listener);

View file

@ -115,9 +115,7 @@ public class TomP2POfferBook implements RemoteOfferBook {
} }
} }
//TODO remove is failing, probably due Coin or Fiat class (was working before) public void removeOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) {
// objects are identical but returned object form network might have some problem with serialisation?
public void removeOffer(Offer offer) {
Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode()); Number160 locationKey = Number160.createHash(offer.getCurrency().getCurrencyCode());
try { try {
final Data offerData = new Data(offer); final Data offerData = new Data(offer);
@ -130,20 +128,22 @@ public class TomP2POfferBook implements RemoteOfferBook {
// We don't test futureRemove.isSuccess() as this API does not fit well to that operation, // We don't test futureRemove.isSuccess() as this API does not fit well to that operation,
// it might change in future to something like foundAndRemoved and notFound // it might change in future to something like foundAndRemoved and notFound
// See discussion at: https://github.com/tomp2p/TomP2P/issues/57#issuecomment-62069840 // See discussion at: https://github.com/tomp2p/TomP2P/issues/57#issuecomment-62069840
log.trace("isRemoved? " + futureRemove.isRemoved());
executor.execute(() -> { executor.execute(() -> {
resultHandler.handleResult();
offerRepositoryListeners.stream().forEach(listener -> { offerRepositoryListeners.stream().forEach(listener -> {
try { try {
Object offerDataObject = offerData.object(); Object offerDataObject = offerData.object();
if (offerDataObject instanceof Offer) { if (offerDataObject instanceof Offer) {
log.trace("Remove offer from DHT was successful. Removed data: [key: " + log.trace("Remove offer from DHT was successful. Removed data: [key: " +
locationKey + ", " + locationKey + ", " +
"offer: " + (Offer) offerDataObject + "]"); "offer: " + offerDataObject + "]");
listener.onOfferRemoved((Offer) offerDataObject); listener.onOfferRemoved((Offer) offerDataObject);
} }
} catch (ClassNotFoundException | IOException e) { } catch (ClassNotFoundException | IOException e) {
e.printStackTrace(); e.printStackTrace();
log.error("Remove offer from DHT failed. Error: " + e.getMessage()); log.error("Remove offer from DHT failed. Error: " + e.getMessage());
faultHandler.handleFault("Remove offer from DHT failed. Error: " + e.getMessage(), e);
} }
}); });
writeInvalidationTimestampToDHT(offer.getCurrency().getCurrencyCode()); writeInvalidationTimestampToDHT(offer.getCurrency().getCurrencyCode());
@ -153,11 +153,13 @@ public class TomP2POfferBook implements RemoteOfferBook {
@Override @Override
public void exceptionCaught(Throwable t) throws Exception { public void exceptionCaught(Throwable t) throws Exception {
log.error("Remove offer from DHT failed. Error: " + t.getMessage()); log.error("Remove offer from DHT failed. Error: " + t.getMessage());
faultHandler.handleFault("Remove offer from DHT failed. Error: " + t.getMessage(), t);
} }
}); });
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
log.error("Remove offer from DHT failed. Error: " + e.getMessage()); log.error("Remove offer from DHT failed. Error: " + e.getMessage());
faultHandler.handleFault("Remove offer from DHT failed. Error: " + e.getMessage(), e);
} }
} }

View file

@ -31,7 +31,7 @@ import io.bitsquare.offer.Offer;
import io.bitsquare.offer.RemoteOfferBook; import io.bitsquare.offer.RemoteOfferBook;
import io.bitsquare.persistence.Persistence; import io.bitsquare.persistence.Persistence;
import io.bitsquare.trade.handlers.TransactionResultHandler; import io.bitsquare.trade.handlers.TransactionResultHandler;
import io.bitsquare.trade.protocol.createoffer.CreateOfferProtocol; import io.bitsquare.trade.protocol.placeoffer.PlaceOfferProtocol;
import io.bitsquare.trade.protocol.trade.TradeMessage; import io.bitsquare.trade.protocol.trade.TradeMessage;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocol; import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocol;
import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocolListener; import io.bitsquare.trade.protocol.trade.offerer.BuyerAcceptsOfferProtocolListener;
@ -49,6 +49,8 @@ import io.bitsquare.trade.protocol.trade.taker.messages.RequestTakeOfferMessage;
import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage; import io.bitsquare.trade.protocol.trade.taker.messages.TakeOfferFeePayedMessage;
import io.bitsquare.user.User; import io.bitsquare.user.User;
import io.bitsquare.util.task.ErrorMessageHandler; import io.bitsquare.util.task.ErrorMessageHandler;
import io.bitsquare.util.task.FaultHandler;
import io.bitsquare.util.task.ResultHandler;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
import org.bitcoinj.core.Transaction; import org.bitcoinj.core.Transaction;
@ -172,41 +174,34 @@ public class TradeManager {
accountSettings.getAcceptedCountries(), accountSettings.getAcceptedCountries(),
accountSettings.getAcceptedLanguageLocales()); accountSettings.getAcceptedLanguageLocales());
CreateOfferProtocol createOfferCoordinator = new CreateOfferProtocol( PlaceOfferProtocol placeOfferProtocol = new PlaceOfferProtocol(
offer, offer,
walletService, walletService,
(transactionId) -> { remoteOfferBook,
try { (transaction) -> {
offer.setOfferFeePaymentTxID(transactionId.getHashAsString()); saveOffer(offer);
addOffer(offer); resultHandler.onResult(transaction);
resultHandler.onResult(transactionId);
} catch (Exception e) {
errorMessageHandler.handleErrorMessage("Could not save offer. Reason: " +
(e.getCause() != null ? e.getCause().getMessage() : e.toString()));
}
}, },
(message, throwable) -> errorMessageHandler.handleErrorMessage(message), (message, throwable) -> errorMessageHandler.handleErrorMessage(message)
remoteOfferBook); );
createOfferCoordinator.createOffer(); placeOfferProtocol.placeOffer();
} }
private void addOffer(Offer offer) { private void saveOffer(Offer offer) {
if (offers.containsKey(offer.getId()))
log.error("An offer with the id " + offer.getId() + " already exists. ");
offers.put(offer.getId(), offer); offers.put(offer.getId(), offer);
persistOffers(); persistOffers();
} }
public void removeOffer(Offer offer) { public void requestRemoveOffer(Offer offer, ResultHandler resultHandler, FaultHandler faultHandler) {
if (!offers.containsKey(offer.getId())) if (offers.containsKey(offer.getId()))
offers.remove(offer.getId());
else
log.error("offers does not contain the offer with the ID " + offer.getId()); log.error("offers does not contain the offer with the ID " + offer.getId());
offers.remove(offer.getId());
persistOffers(); persistOffers();
remoteOfferBook.removeOffer(offer); remoteOfferBook.removeOffer(offer, resultHandler, faultHandler);
} }
@ -261,7 +256,7 @@ public class TradeManager {
public void onOfferAccepted(Offer offer) { public void onOfferAccepted(Offer offer) {
trade.setState(Trade.State.OFFERER_ACCEPTED); trade.setState(Trade.State.OFFERER_ACCEPTED);
persistPendingTrades(); persistPendingTrades();
removeOffer(offer); requestRemoveOffer(offer);
} }
@Override @Override

View file

@ -15,7 +15,7 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. * along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.bitsquare.trade.protocol.createoffer; package io.bitsquare.trade.protocol.placeoffer;
import io.bitsquare.btc.WalletService; import io.bitsquare.btc.WalletService;
import io.bitsquare.offer.Offer; import io.bitsquare.offer.Offer;
@ -35,9 +35,9 @@ import org.slf4j.LoggerFactory;
* Responsible for coordinating tasks involved in the create offer process. * Responsible for coordinating tasks involved in the create offer process.
* Executed on UI thread (single threaded) * Executed on UI thread (single threaded)
*/ */
public class CreateOfferProtocol { public class PlaceOfferProtocol {
private static final Logger log = LoggerFactory.getLogger(CreateOfferProtocol.class); private static final Logger log = LoggerFactory.getLogger(PlaceOfferProtocol.class);
private final Offer offer; private final Offer offer;
private final WalletService walletService; private final WalletService walletService;
@ -46,8 +46,8 @@ public class CreateOfferProtocol {
private final RemoteOfferBook remoteOfferBook; private final RemoteOfferBook remoteOfferBook;
private int repeatAddOfferCallCounter = 0; private int repeatAddOfferCallCounter = 0;
public CreateOfferProtocol(Offer offer, WalletService walletService, TransactionResultHandler resultHandler, public PlaceOfferProtocol(Offer offer, WalletService walletService, RemoteOfferBook remoteOfferBook, TransactionResultHandler resultHandler,
FaultHandler faultHandler, RemoteOfferBook remoteOfferBook) { FaultHandler faultHandler) {
this.offer = offer; this.offer = offer;
this.walletService = walletService; this.walletService = walletService;
this.resultHandler = resultHandler; this.resultHandler = resultHandler;
@ -55,18 +55,16 @@ public class CreateOfferProtocol {
this.remoteOfferBook = remoteOfferBook; this.remoteOfferBook = remoteOfferBook;
} }
public void createOffer() { public void placeOffer() {
try { try {
validateOffer(); validateOffer();
Transaction transaction = createOfferFeeTx(); Transaction transaction = createOfferFeeTx();
TransactionResultHandler resultHandler1 = transaction1 -> addOffer(transaction1); TransactionResultHandler resultHandler1 = transaction1 -> addOffer(transaction1);
FaultHandler faultHandler1 = (message, throwable) -> faultHandler.handleFault(message, throwable); FaultHandler faultHandler1 = (message, throwable) -> faultHandler.handleFault(message, throwable);
broadcastCreateOfferFeeTx(transaction, resultHandler1, faultHandler1); broadcastCreateOfferFeeTx(transaction, resultHandler1, faultHandler1);
} catch (Throwable t) { } catch (Throwable t) {
// handled in specific methods
} }
} }
// 1. Validate offer data // 1. Validate offer data
@ -128,9 +126,11 @@ public class CreateOfferProtocol {
// Async // Async
// In case of an error: Try again, afterwards give up. // In case of an error: Try again, afterwards give up.
void addOffer(Transaction transaction) { void addOffer(Transaction transaction) {
// need to write data before storage, otherwise hash is different when removing offer!
offer.setOfferFeePaymentTxID(transaction.getHashAsString());
remoteOfferBook.addOffer(offer, remoteOfferBook.addOffer(offer,
() -> { () -> {
offer.setOfferFeePaymentTxID(transaction.getHashAsString());
resultHandler.onResult(transaction); resultHandler.onResult(transaction);
}, },
(message, throwable) -> { (message, throwable) -> {

View file

@ -19,15 +19,15 @@ package viewfx.model.support;
import viewfx.model.Activatable; import viewfx.model.Activatable;
public abstract class ActivatableWithDelegate<D extends Activatable> extends WithDelegate<D> implements Activatable { public abstract class ActivatableWithDataModel<D extends Activatable> extends WithDataModel<D> implements Activatable {
public ActivatableWithDelegate(D delegate) { public ActivatableWithDataModel(D dataModel) {
super(delegate); super(dataModel);
} }
@Override @Override
public final void activate() { public final void activate() {
delegate.activate(); dataModel.activate();
this.doActivate(); this.doActivate();
} }
@ -36,7 +36,7 @@ public abstract class ActivatableWithDelegate<D extends Activatable> extends Wit
@Override @Override
public final void deactivate() { public final void deactivate() {
delegate.deactivate(); dataModel.deactivate();
this.doDeactivate(); this.doDeactivate();
} }

View file

@ -19,11 +19,11 @@ package viewfx.model.support;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
public abstract class WithDelegate<D> { public abstract class WithDataModel<D> {
protected final D delegate; protected final D dataModel;
protected WithDelegate(D delegate) { protected WithDataModel(D dataModel) {
this.delegate = checkNotNull(delegate, "Delegate object must not be null"); this.dataModel = checkNotNull(dataModel, "Delegate object must not be null");
} }
} }

View file

@ -27,11 +27,11 @@ import viewfx.view.ViewLoader;
public class CachingViewLoader implements ViewLoader { public class CachingViewLoader implements ViewLoader {
private final HashMap<Object, View> cache = new HashMap<>(); private final HashMap<Object, View> cache = new HashMap<>();
private final ViewLoader delegate; private final ViewLoader viewLoader;
@Inject @Inject
public CachingViewLoader(ViewLoader delegate) { public CachingViewLoader(ViewLoader viewLoader) {
this.delegate = delegate; this.viewLoader = viewLoader;
} }
@Override @Override
@ -39,7 +39,7 @@ public class CachingViewLoader implements ViewLoader {
if (cache.containsKey(viewClass)) if (cache.containsKey(viewClass))
return cache.get(viewClass); return cache.get(viewClass);
View view = delegate.load(viewClass); View view = viewLoader.load(viewClass);
cache.put(viewClass, view); cache.put(viewClass, view);
return view; return view;
} }

View file

@ -15,7 +15,7 @@
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. * along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/ */
package io.bitsquare.trade.protocol.createoffer; package io.bitsquare.trade.protocol.placeoffer;
import io.bitsquare.arbitrator.Arbitrator; import io.bitsquare.arbitrator.Arbitrator;
import io.bitsquare.bank.BankAccountType; import io.bitsquare.bank.BankAccountType;
@ -76,8 +76,8 @@ import static org.junit.Assert.*;
* 4. Start BootstrapNodeMain at localhost with program args: --node.name localhost * 4. Start BootstrapNodeMain at localhost with program args: --node.name localhost
*/ */
@Ignore @Ignore
public class CreateOfferProtocolTest { public class PlaceOfferProtocolTest {
private static final Logger log = LoggerFactory.getLogger(CreateOfferProtocolTest.class); private static final Logger log = LoggerFactory.getLogger(PlaceOfferProtocolTest.class);
private WalletService walletService; private WalletService walletService;
private TomP2PMessageService messageService; private TomP2PMessageService messageService;
@ -201,9 +201,9 @@ public class CreateOfferProtocolTest {
throwable.printStackTrace(); throwable.printStackTrace();
fail(throwable.getMessage()); fail(throwable.getMessage());
}; };
CreateOfferProtocol createOfferCoordinator = getCreateOfferCoordinator(offer); PlaceOfferProtocol placeOfferProtocol = getCreateOfferCoordinator(offer);
Transaction transaction = createOfferCoordinator.createOfferFeeTx(); Transaction transaction = placeOfferProtocol.createOfferFeeTx();
createOfferCoordinator.broadcastCreateOfferFeeTx(transaction, resultHandler, faultHandler); placeOfferProtocol.broadcastCreateOfferFeeTx(transaction, resultHandler, faultHandler);
log.info("Balance post = " + walletService.getBalanceForAddress(address)); log.info("Balance post = " + walletService.getBalanceForAddress(address));
} catch (Exception e) { } catch (Exception e) {
@ -246,9 +246,9 @@ public class CreateOfferProtocolTest {
countDownLatch.countDown(); countDownLatch.countDown();
countDownLatch.countDown(); countDownLatch.countDown();
}; };
CreateOfferProtocol createOfferCoordinator = getCreateOfferCoordinator(offer, resultHandler, faultHandler); PlaceOfferProtocol placeOfferProtocol = getPlaceOfferProtocol(offer, resultHandler, faultHandler);
Transaction transaction = createOfferCoordinator.createOfferFeeTx(); Transaction transaction = placeOfferProtocol.createOfferFeeTx();
createOfferCoordinator.addOffer(transaction); placeOfferProtocol.addOffer(transaction);
countDownLatch.await(); countDownLatch.await();
log.info("Finished"); log.info("Finished");
} catch (Exception e) { } catch (Exception e) {
@ -260,7 +260,7 @@ public class CreateOfferProtocolTest {
} }
@Test @Test
public void createOfferTest() throws InterruptedException { public void placeOfferTest() throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1); CountDownLatch countDownLatch = new CountDownLatch(1);
TransactionResultHandler resultHandler = transaction -> { TransactionResultHandler resultHandler = transaction -> {
assertNotNull(transaction); assertNotNull(transaction);
@ -273,29 +273,29 @@ public class CreateOfferProtocolTest {
countDownLatch.countDown(); countDownLatch.countDown();
countDownLatch.countDown(); countDownLatch.countDown();
}; };
CreateOfferProtocol createOfferCoordinator = getCreateOfferCoordinator(getOffer(), resultHandler, faultHandler); PlaceOfferProtocol placeOfferProtocol = getPlaceOfferProtocol(getOffer(), resultHandler, faultHandler);
createOfferCoordinator.createOffer(); placeOfferProtocol.placeOffer();
countDownLatch.await(); countDownLatch.await();
} }
private CreateOfferProtocol getCreateOfferCoordinator(Offer offer) throws InterruptedException { private PlaceOfferProtocol getCreateOfferCoordinator(Offer offer) throws InterruptedException {
TransactionResultHandler resultHandler = transaction -> log.debug("result transaction=" + transaction.toString()); TransactionResultHandler resultHandler = transaction -> log.debug("result transaction=" + transaction.toString());
FaultHandler faultHandler = (message, throwable) -> { FaultHandler faultHandler = (message, throwable) -> {
log.error(message); log.error(message);
throwable.printStackTrace(); throwable.printStackTrace();
log.info("Balance = " + walletService.getBalanceForAddress(walletService.getAddressInfoByTradeID(OFFER_ID).getAddress())); log.info("Balance = " + walletService.getBalanceForAddress(walletService.getAddressInfoByTradeID(OFFER_ID).getAddress()));
}; };
return getCreateOfferCoordinator(offer, resultHandler, faultHandler); return getPlaceOfferProtocol(offer, resultHandler, faultHandler);
} }
private CreateOfferProtocol getCreateOfferCoordinator(Offer offer, TransactionResultHandler resultHandler, FaultHandler faultHandler) throws private PlaceOfferProtocol getPlaceOfferProtocol(Offer offer, TransactionResultHandler resultHandler, FaultHandler faultHandler) throws
InterruptedException { InterruptedException {
return new CreateOfferProtocol(offer, return new PlaceOfferProtocol(offer,
walletService, walletService,
remoteOfferBook,
resultHandler, resultHandler,
faultHandler, faultHandler);
remoteOfferBook);
} }
private Offer getOffer() { private Offer getOffer() {