Add online state icons to offerbook

This commit is contained in:
Manfred Karrer 2015-03-09 15:32:12 +01:00
parent 9c8ae1bc10
commit 397aedc099
15 changed files with 122 additions and 27 deletions

View File

@ -155,4 +155,17 @@
#image-update-failed {
-fx-image: url("../../../images/update/update_failed.png");
}
/* offer state */
#image-offer_state_unknown {
-fx-image: url("../../../images/offer/offer_state_unknown.png");
}
#image-offer_state_available {
-fx-image: url("../../../images/offer/offer_state_available.png");
}
#image-offer_state_not_available {
-fx-image: url("../../../images/offer/offer_state_not_available.png");
}

View File

@ -137,7 +137,7 @@
<!--<TableColumn text="Country" fx:id="countryColumn" minWidth="60"/>-->
<TableColumn text="Bank transfer type" fx:id="bankAccountTypeColumn" minWidth="130"/>
<TableColumn text="" fx:id="directionColumn" minWidth="80" sortable="false"/>
<TableColumn text="Online" fx:id="statusColumn" minWidth="20" sortable="false"/>
</columns>
</TableView>

View File

@ -42,7 +42,9 @@ import javax.inject.Inject;
import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
@ -67,7 +69,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
@FXML InputTextField volumeTextField, amountTextField, priceTextField;
@FXML Button createOfferButton, showAdvancedSettingsButton, openCountryFilterButton, openPaymentMethodsFilterButton;
@FXML TableColumn<OfferBookListItem, OfferBookListItem> priceColumn, amountColumn, volumeColumn, directionColumn,
/*countryColumn,*/ bankAccountTypeColumn;
/*countryColumn,*/ bankAccountTypeColumn, statusColumn;
@FXML Label amountBtcLabel, priceDescriptionLabel, priceFiatLabel, volumeDescriptionLabel, volumeFiatLabel,
extendedButton1Label, extendedButton2Label, extendedCheckBoxLabel;
@ -107,6 +109,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
/* setCountryColumnCellFactory();*/
setBankAccountTypeColumnCellFactory();
setDirectionColumnCellFactory();
setStatusColumnCellFactory();
table.getSortOrder().add(priceColumn);
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
@ -480,6 +483,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
button.setOnAction(event -> takeOffer(item.getOffer()));
}
//TODO remove listener
item.bankAccountCountryProperty().addListener((ov, o, n) ->
verifyIfTradable(item));
verifyIfTradable(item);
@ -496,6 +500,66 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
});
}
private void setStatusColumnCellFactory() {
statusColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
statusColumn.setCellFactory(
new Callback<TableColumn<OfferBookListItem, OfferBookListItem>, TableCell<OfferBookListItem,
OfferBookListItem>>() {
@Override
public TableCell<OfferBookListItem, OfferBookListItem> call(
TableColumn<OfferBookListItem, OfferBookListItem> column) {
return new TableCell<OfferBookListItem, OfferBookListItem>() {
final ImageView iconView = new ImageView();
private ChangeListener<Offer.State> stateChangeListener;
private ObjectProperty<Offer.State> stateProperty;
private void updateIcon(final OfferBookListItem item) {
Offer offer = item.getOffer();
if (model.isMyOffer(offer)) {
iconView.setId("image-offer_state_available");
}
else {
switch (offer.getState()) {
case UNKNOWN:
iconView.setId("image-offer_state_unknown");
break;
case OFFER_AVAILABLE:
iconView.setId("image-offer_state_available");
break;
case OFFER_NOT_AVAILABLE:
case OFFER_REMOVED:
iconView.setId("image-offer_state_not_available");
break;
}
}
}
@Override
public void updateItem(final OfferBookListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
stateProperty = item.getOffer().getStateProperty();
this.stateChangeListener = (ov, o, n) -> updateIcon(item);
stateProperty.addListener(stateChangeListener);
updateIcon(item);
setGraphic(iconView);
}
else {
if (stateProperty != null) {
stateProperty.removeListener(stateChangeListener);
stateChangeListener = null;
}
setGraphic(null);
}
}
};
}
});
}
/* private void setCountryColumnCellFactory() {
countryColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
countryColumn.setCellFactory(

View File

@ -82,7 +82,7 @@ class TakeOfferDataModel implements Activatable, DataModel {
final ObjectProperty<Offer.State> offerIsAvailable = new SimpleObjectProperty<>(Offer.State.UNKNOWN);
@Inject
public TakeOfferDataModel(TradeManager tradeManager,
public TakeOfferDataModel(TradeManager tradeManager,
WalletService walletService,
Preferences preferences,
Persistence persistence) {
@ -103,6 +103,7 @@ class TakeOfferDataModel implements Activatable, DataModel {
@Override
public void deactivate() {
btcCode.unbind();
tradeManager.stopRequestIsOfferAvailableRequest(offer);
}
void initWithData(Coin amount, Offer offer) {

View File

@ -47,6 +47,7 @@ import viewfx.view.FxmlView;
import viewfx.view.support.ActivatableViewAndModel;
import javafx.beans.property.BooleanProperty;
import javafx.beans.value.ChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.HPos;
@ -95,6 +96,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
private final Navigation navigation;
private final OverlayManager overlayManager;
private ChangeListener<Offer.State> offerIsAvailableChangeListener;
@Inject
private TakeOfferView(TakeOfferViewModel model, Navigation navigation,
@ -111,6 +113,12 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
setupBindings();
}
@Override
protected void doDeactivate() {
if (offerIsAvailableChangeListener != null)
model.offerIsAvailable.removeListener(offerIsAvailableChangeListener);
}
public void initWithData(Direction direction, Coin amount, Offer offer) {
model.initWithData(direction, amount, offer);
@ -140,18 +148,18 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
acceptedLanguagesTextField.setText(model.getAcceptedLanguages());
acceptedArbitratorsTextField.setText(model.getAcceptedArbitrators());
model.offerIsAvailable.addListener((ov, oldValue, newValue) -> handleOfferIsAvailableState(newValue));
offerIsAvailableChangeListener = (ov, oldValue, newValue) -> handleOfferIsAvailableState(newValue);
model.offerIsAvailable.addListener(offerIsAvailableChangeListener);
handleOfferIsAvailableState(model.offerIsAvailable.get());
}
private void handleOfferIsAvailableState(Offer.State state) {
isOfferAvailableLabel.setVisible(false);
isOfferAvailableLabel.setManaged(false);
isOfferAvailableProgressIndicator.setProgress(0);
isOfferAvailableProgressIndicator.setVisible(false);
isOfferAvailableProgressIndicator.setManaged(false);
if ((state == Offer.State.OFFER_AVAILABLE)) {
if (state == Offer.State.OFFER_AVAILABLE) {
isOfferAvailableLabel.setVisible(false);
isOfferAvailableLabel.setManaged(false);
isOfferAvailableProgressIndicator.setProgress(0);
isOfferAvailableProgressIndicator.setVisible(false);
isOfferAvailableProgressIndicator.setManaged(false);
showPaymentInfoScreenButton.setVisible(true);
}
else if ((state == Offer.State.OFFER_NOT_AVAILABLE)) {
@ -173,7 +181,6 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
@FXML
void onTakeOffer() {
model.takeOffer();
}
@FXML
@ -261,7 +268,8 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
// Might fix #315 Offerbook tab gets closed
//tabPane.getTabs().remove(tabPane.getSelectionModel().getSelectedItem());
tabPane.getTabs().remove(1);
if (tabPane != null && tabPane.getTabs() != null && tabPane.getTabs().size() > 1)
tabPane.getTabs().remove(1);
}
private void setupListeners() {

View File

@ -80,7 +80,7 @@ public class Offer implements Serializable {
private String offerFeePaymentTxID;
// Those state properties are transient and only used at runtime!
private transient State state = State.UNKNOWN;
private transient State state;
// don't access directly as it might be null; use getStateProperty() which creates an object if not instantiated
private transient ObjectProperty<State> stateProperty;
@ -120,6 +120,7 @@ public class Offer implements Serializable {
this.acceptedLanguageLocales = acceptedLanguageLocales;
creationDate = new Date();
state = State.UNKNOWN;
getStateProperty().set(state);
}
@ -225,6 +226,9 @@ public class Offer implements Serializable {
}
public State getState() {
if(state == null)
setState(State.UNKNOWN);
return state;
}

View File

@ -94,7 +94,7 @@ public class OfferBook {
offer.setState(Offer.State.OFFER_REMOVED);
// clean up possible references in tradeManager
tradeManager.handleRemovedOffer(offer);
tradeManager.onOfferRemovedFromRemoteOfferBook(offer);
offerBookListItems.removeIf(item -> item.getOffer().getId().equals(offer.getId()));
}

View File

@ -436,8 +436,13 @@ public class TradeManager {
log.warn("requestIsOfferAvailable already called for offer with ID:" + offer.getId());
}
}
public void handleRemovedOffer(Offer offer) {
// When closing take offer view, we are not interested in the requestIsOfferAvailable result anymore, so remove from the map
public void stopRequestIsOfferAvailableRequest(Offer offer) {
requestIsOfferAvailableProtocolMap.remove(offer.getId());
}
public void onOfferRemovedFromRemoteOfferBook(Offer offer) {
requestIsOfferAvailableProtocolMap.remove(offer.getId());
}

View File

@ -70,31 +70,31 @@ public class RequestIsOfferAvailableProtocol {
// 1. GetPeerAddress
// Async
// In case of an error: Repeat once, then give up.
// In case of an error: Don't repeat call for now, maybe in production repeat once.
private void getPeerAddress() {
log.debug("getPeerAddress called");
GetPeerAddress.run(this::onResultGetPeerAddress, this::onGetPeerAddressFault, tradeMessageService, offererMessagePublicKey);
}
private void onGetPeerAddressFault(String errorMessage) {
GetPeerAddress.run(this::onResultGetPeerAddress, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey);
}
/* private void onGetPeerAddressFault(String errorMessage) {
GetPeerAddress.run(this::onResultGetPeerAddress, this::handleErrorMessage, tradeMessageService, offererMessagePublicKey);
}*/
// 2. RequestTakeOffer
// Async
// In case of an error: Repeat once, then give up.
// In case of an error: Don't repeat call for now, maybe in production repeat once.
public void onResultGetPeerAddress(Peer peer) {
log.debug("onResultGetPeerAddress called");
this.peer = peer;
RequestIsOfferAvailable.run(this::onRequestIsOfferAvailableFault, peer, tradeMessageService, offerId);
}
private void onRequestIsOfferAvailableFault(String errorMessage) {
RequestIsOfferAvailable.run(this::handleErrorMessage, peer, tradeMessageService, offerId);
}
/* private void onRequestIsOfferAvailableFault(String errorMessage) {
RequestIsOfferAvailable.run(this::handleErrorMessage, peer, tradeMessageService, offerId);
}*/
// generic
private void handleErrorMessage(String errorMessage) {
offer.setState(Offer.State.OFFER_NOT_AVAILABLE);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB