From 397aedc099170e37134e3724b176a3cabe63e5d4 Mon Sep 17 00:00:00 2001 From: Manfred Karrer Date: Mon, 9 Mar 2015 15:32:12 +0100 Subject: [PATCH] Add online state icons to offerbook --- gui/src/main/java/io/bitsquare/gui/images.css | 13 ++++ .../main/trade/offerbook/OfferBookView.fxml | 2 +- .../main/trade/offerbook/OfferBookView.java | 66 +++++++++++++++++- .../trade/takeoffer/TakeOfferDataModel.java | 3 +- .../main/trade/takeoffer/TakeOfferView.java | 28 +++++--- .../main/java/io/bitsquare/offer/Offer.java | 6 +- .../java/io/bitsquare/offer/OfferBook.java | 2 +- .../java/io/bitsquare/trade/TradeManager.java | 9 ++- .../RequestIsOfferAvailableProtocol.java | 20 +++--- .../images/offer/offer_state_available.png | Bin 0 -> 3727 bytes .../images/offer/offer_state_available@2x.png | Bin 0 -> 5422 bytes .../offer/offer_state_not_available.png | Bin 0 -> 3740 bytes .../offer/offer_state_not_available@2x.png | Bin 0 -> 5448 bytes .../images/offer/offer_state_unknown.png | Bin 0 -> 3729 bytes .../images/offer/offer_state_unknown@2x.png | Bin 0 -> 5412 bytes 15 files changed, 122 insertions(+), 27 deletions(-) create mode 100644 gui/src/main/resources/images/offer/offer_state_available.png create mode 100644 gui/src/main/resources/images/offer/offer_state_available@2x.png create mode 100644 gui/src/main/resources/images/offer/offer_state_not_available.png create mode 100644 gui/src/main/resources/images/offer/offer_state_not_available@2x.png create mode 100644 gui/src/main/resources/images/offer/offer_state_unknown.png create mode 100644 gui/src/main/resources/images/offer/offer_state_unknown@2x.png diff --git a/gui/src/main/java/io/bitsquare/gui/images.css b/gui/src/main/java/io/bitsquare/gui/images.css index 65c9544bfd..8e8a39793a 100644 --- a/gui/src/main/java/io/bitsquare/gui/images.css +++ b/gui/src/main/java/io/bitsquare/gui/images.css @@ -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"); } \ No newline at end of file diff --git a/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.fxml b/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.fxml index e2d5afc727..e1bb246be1 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.fxml @@ -137,7 +137,7 @@ - + diff --git a/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.java b/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.java index 6d0489a349..5f998ade96 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/trade/offerbook/OfferBookView.java @@ -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 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 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 new ReadOnlyObjectWrapper<>(offer.getValue())); + statusColumn.setCellFactory( + new Callback, TableCell>() { + + @Override + public TableCell call( + TableColumn column) { + return new TableCell() { + final ImageView iconView = new ImageView(); + private ChangeListener stateChangeListener; + private ObjectProperty 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( diff --git a/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java b/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java index 517d8b190f..9c7640a265 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferDataModel.java @@ -82,7 +82,7 @@ class TakeOfferDataModel implements Activatable, DataModel { final ObjectProperty 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) { diff --git a/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java b/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java index fafff6f883..f24d65e920 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/trade/takeoffer/TakeOfferView.java @@ -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 offerIsAvailableChangeListener; @Inject private TakeOfferView(TakeOfferViewModel model, Navigation navigation, @@ -111,6 +113,12 @@ public class TakeOfferView extends ActivatableViewAndModel 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 1) + tabPane.getTabs().remove(1); } private void setupListeners() { diff --git a/gui/src/main/java/io/bitsquare/offer/Offer.java b/gui/src/main/java/io/bitsquare/offer/Offer.java index e567dbdb3d..5ac81ef9f0 100644 --- a/gui/src/main/java/io/bitsquare/offer/Offer.java +++ b/gui/src/main/java/io/bitsquare/offer/Offer.java @@ -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 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; } diff --git a/gui/src/main/java/io/bitsquare/offer/OfferBook.java b/gui/src/main/java/io/bitsquare/offer/OfferBook.java index 3c26572a53..998edcdadd 100644 --- a/gui/src/main/java/io/bitsquare/offer/OfferBook.java +++ b/gui/src/main/java/io/bitsquare/offer/OfferBook.java @@ -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())); } diff --git a/gui/src/main/java/io/bitsquare/trade/TradeManager.java b/gui/src/main/java/io/bitsquare/trade/TradeManager.java index 2d211ee10c..4758e8bf40 100644 --- a/gui/src/main/java/io/bitsquare/trade/TradeManager.java +++ b/gui/src/main/java/io/bitsquare/trade/TradeManager.java @@ -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()); } diff --git a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java index 832bb0f723..68ee43a75b 100644 --- a/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java +++ b/gui/src/main/java/io/bitsquare/trade/protocol/trade/taker/RequestIsOfferAvailableProtocol.java @@ -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); diff --git a/gui/src/main/resources/images/offer/offer_state_available.png b/gui/src/main/resources/images/offer/offer_state_available.png new file mode 100644 index 0000000000000000000000000000000000000000..05b73c83259d1bc77b66c088deda63d3fde85172 GIT binary patch literal 3727 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+xS29TB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN*i1Q(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!8hNY6+&*}%+L!PHpK z*wo0($V5lM$iTot-@sho*g)6N!pgwZ%EV9s3Y6@)6l{u8(yW49+@RJ0dA3R!B_#z` z`ugSN<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF${-^kX1JslCl_TFlw{`T zDS*sOOv*1Uu~kw6$}7P9l3M^bJg*oUUcivkuShJ=H`FuGM^>DY3|CuFT9gBJMoO}N zYEEiyYFmH5r4beZ1KP^DC^fMpzbGU>KL-|`0WgCUoP$ji zd=ry1^FRiJ-3Hf^>XKNJYO7>qU}&mqV61Ck5@KjzWny7vY@%&oXk}mkSM8ghl9^UX zv}#}srzDmn5~DsP*(xo+C^r!p$eEyYsb7$n4z?EVRV(NGocto73xF;)Mw9Y%b`B`Y zPs_{!$`uE>J1Ka&I-404XyJlJM=>JTJ;N@7!Iz|Jk|r;(VoJjfXAM)6TvBbI#H@<>5Cb z2Mrc+k5rzBT1ghZ+r}TiO}y!}@k8sBM+{5dmR^mSzdkHX&-(4R&--HJ%ii7K^b|QU zH~!s$?@TO?4GT9aR^NZ|?|sNA>$i&xg;tfhIZBAMZSXjGe)7er7Z-LuyPRI^<>BVb zwdq|>!prxn7H`kp51t0iS{K4&S8OoJu5a&;CsBVL{~Ax$ z?wgZZzgz5YSt>UK3- zE(-SA1%H3WFrASzReZK*=`sro&DzP_+bk3lmkXJ{n;hbJE5+x}Y}KcSCrP@coY39o zv{`liiu}u*4mN`GoQ`Q3NA28Qvh)57jx#G(9G7fp7ZMa+&)HwPBlY!Xg%63Y`3oG5 z@80t9_~OdVn|GT{vt>MAeo#3!{fiYxvP_`J?O%?rHjEZ2^P5UOpS~hiR{ZqcsiWoP za}P7rvd8Whw%6fR5~}3fk@=eOcP!8HWgo--@ksf<5`XdGfx$KL`R8q8GVa<~*0C<0 znfWC~UiN(JYRSsR<;^iAF>kA_ir=x=$<8}`>e4G!y~FZnW31Z$J~b@+zx?;+xc3Vz zD*wDXv$*kgMBY88)2r3)Zd=hC^vzdB^L#@8Pr-jbH-D<#e%;R6)O4xG-DFf^5j(^S`S+p am>Kx2Pk&zSv(XRKMf7y_b6Mw<&;$UI3W}Nl literal 0 HcmV?d00001 diff --git a/gui/src/main/resources/images/offer/offer_state_available@2x.png b/gui/src/main/resources/images/offer/offer_state_available@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ecad0b0c8c9e73b847952c591e721e2302360393 GIT binary patch literal 5422 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 LIa+eDhfe+jRFVL% literal 0 HcmV?d00001 diff --git a/gui/src/main/resources/images/offer/offer_state_unknown.png b/gui/src/main/resources/images/offer/offer_state_unknown.png new file mode 100644 index 0000000000000000000000000000000000000000..6cdbc05fd8fbf19e9e064bd21f196441b563c057 GIT binary patch literal 3729 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+xS29TB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN*i1Q(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!8hNY6+&*}%+L!PHpK z*wo0($V5lM$iTot-@sho*g)6N!pgwZ%EV9s3Y6@)6l{u8(yW49+@RJ0dA3R!B_#z` z`ugSN<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF${-^kX1JslCl_TFlw{`T zDS*sOOv*1Uu~kw6$}7P9l3M^bJg*oUUcivkuShJ=H`FuGM^>DY3|CuFT9gBJMoO}N zYEEiyYFmH5r4beZ1KP^DC^fMpzbGU>KL-|`0WgCUoP$ji zd=ry1^FRiJ-3Hf^>XKNJYO7>qU}&mqV61Ck5@KjzWny7vY@%&oXk}mkSM8ghl9^UX zv}#}srzDmn5~DsP*(xo+C^r!p$eEyYsb7$n4z?EVRV(NGocto73xF;)Mw9Y%b`B`Y zPs_{!$`uE>J1Ka&I-40d+8FG3$KlbLR{I9#-Vi7K z4yCwPYa23FHF3CV=^oWP+dRwRs!i7Mk9O(lWj`t(PdVF4j|c;I(yYnt|)mH&h6FJ_sAfA(W!{%gH3lF97%SN;!w z1QI2H&C(+`qgU=pGyJcrCzUE{p8MhmgR#i@J7OE&$acTwo4xPj^;26WMa@uS=5~^| zk6*FyYR-GhKR=v}FW$Q8e)wyoL??e<+QFTjDiZ^YoDOlHcssA9?AZR875@!IyI-hr zFXosi;CJoRoUV2AYh1RSQ<^QkWQ)%PJCmd5Gn~u)nHu*uzFDV!pxo}~%d5XG6`$da znbG!nS&a4HydTdCZ~Tl+@jhmisu8fJr_VBZYop)&-?=>MRO^H40E-XjDvK9bd|377%+$yo47tInTd!|U`!9Sc)5}w8 zE=$wtfOj=lWu#8-+3@ps(zKt`C$10@wQ&zj={(%IxFfS9Ht6&UNre!>h5RkLCmuxI zd-E-F^#skAmnt;DwC3wvk#oqrk5+R$aR%;$sl<~F_~UDBMf6R!DBEWh^n z)myVKMweGknIiVa$MeHZ3Mq`y6WQ~S7A`#m=O zp2Ow0J08vGNbzA&d^&B#8?GZ9cYGt39>1{vy@pip((gZByfYHhU*lI_p7*!=)DzDe z&XZLh9sX|fqtX4L&@Z_=ectaGix&GY{&S#xM@aNPg}_J2#R_dCI^?m*N)Lu$j`ts2v d!Fp~3hRnD7#U9-~oDAwDdb;|#taD0e0swfpn@s=! literal 0 HcmV?d00001 diff --git a/gui/src/main/resources/images/offer/offer_state_unknown@2x.png b/gui/src/main/resources/images/offer/offer_state_unknown@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1a9e52c359e94947dda8c46ef427de7b8f68f01f GIT binary patch literal 5412 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