/*
* This file is part of Bitsquare.
*
* Bitsquare is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Bitsquare is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
*/
package io.bitsquare.gui.main.offer;
import io.bitsquare.btc.pricefeed.PriceFeedService;
import io.bitsquare.common.UserThread;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableView;
import io.bitsquare.gui.common.view.View;
import io.bitsquare.gui.common.view.ViewLoader;
import io.bitsquare.gui.components.InputTextField;
import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.offer.createoffer.CreateOfferView;
import io.bitsquare.gui.main.offer.offerbook.OfferBookView;
import io.bitsquare.gui.main.offer.takeoffer.TakeOfferView;
import io.bitsquare.gui.main.overlays.popups.Popup;
import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.trade.offer.Offer;
import io.bitsquare.user.Preferences;
import javafx.beans.value.ChangeListener;
import javafx.collections.ListChangeListener;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.AnchorPane;
import java.util.List;
import java.util.Optional;
public abstract class OfferView extends ActivatableView<TabPane, Void> {
private OfferBookView offerBookView;
private CreateOfferView createOfferView;
private TakeOfferView takeOfferView;
private AnchorPane createOfferPane;
private AnchorPane takeOfferPane;
private Navigation.Listener navigationListener;
private Offer offer;
private final ViewLoader viewLoader;
private final Navigation navigation;
private final PriceFeedService priceFeedService;
private Preferences preferences;
private final Offer.Direction direction;
private Tab takeOfferTab, createOfferTab, offerBookTab;
private TradeCurrency tradeCurrency;
private boolean createOfferViewOpen, takeOfferViewOpen;
private ChangeListener<Tab> tabChangeListener;
private ListChangeListener<Tab> tabListChangeListener;
protected OfferView(ViewLoader viewLoader, Navigation navigation, PriceFeedService priceFeedService, Preferences preferences) {
this.viewLoader = viewLoader;
this.navigation = navigation;
this.priceFeedService = priceFeedService;
this.preferences = preferences;
this.direction = (this instanceof BuyOfferView) ? Offer.Direction.BUY : Offer.Direction.SELL;
}
@Override
protected void initialize() {
navigationListener = viewPath -> {
if (viewPath.size() == 3 && viewPath.indexOf(this.getClass()) == 1)
loadView(viewPath.tip());
};
tabChangeListener = (observableValue, oldValue, newValue) -> {
UserThread.execute(InputTextField::hideErrorMessageDisplay);
if (newValue != null) {
if (newValue.equals(createOfferTab) && createOfferView != null) {
createOfferView.onTabSelected(true);
} else if (newValue.equals(takeOfferTab) && takeOfferView != null) {
takeOfferView.onTabSelected(true);
} else if (newValue.equals(offerBookTab) && offerBookView != null) {
offerBookView.onTabSelected(true);
}
}
if (oldValue != null) {
if (oldValue.equals(createOfferTab) && createOfferView != null) {
createOfferView.onTabSelected(false);
} else if (oldValue.equals(takeOfferTab) && takeOfferView != null) {
takeOfferView.onTabSelected(false);
} else if (oldValue.equals(offerBookTab) && offerBookView != null) {
offerBookView.onTabSelected(false);
}
}
};
tabListChangeListener = change -> {
change.next();
List<? extends Tab> removedTabs = change.getRemoved();
if (removedTabs.size() == 1) {
if (removedTabs.get(0).getContent().equals(createOfferPane))
onCreateOfferViewRemoved();
else if (removedTabs.get(0).getContent().equals(takeOfferPane))
onTakeOfferViewRemoved();
}
};
}
@Override
protected void activate() {
Optional<TradeCurrency> tradeCurrencyOptional = (this instanceof SellOfferView) ?
CurrencyUtil.getTradeCurrency(preferences.getSellScreenCurrencyCode()) :
CurrencyUtil.getTradeCurrency(preferences.getBuyScreenCurrencyCode());
if (tradeCurrencyOptional.isPresent())
tradeCurrency = tradeCurrencyOptional.get();
else {
tradeCurrency = CurrencyUtil.getDefaultTradeCurrency();
}
root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener);
root.getTabs().addListener(tabListChangeListener);
navigation.addListener(navigationListener);
navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class);
}
@Override
protected void deactivate() {
navigation.removeListener(navigationListener);
root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener);
root.getTabs().removeListener(tabListChangeListener);
}
private void loadView(Class<? extends View> viewClass) {
TabPane tabPane = root;
View view;
boolean isBuy = direction == Offer.Direction.BUY;
if (viewClass == OfferBookView.class && offerBookView == null) {
view = viewLoader.load(viewClass);
// Offerbook must not be cached by ViewLoader as we use 2 instances for sell and buy screens.
offerBookTab = new Tab(isBuy ? "Buy bitcoin" : "Sell bitcoin");
offerBookTab.setClosable(false);
offerBookTab.setContent(view.getRoot());
tabPane.getTabs().add(offerBookTab);
offerBookView = (OfferBookView) view;
offerBookView.onTabSelected(true);
OfferActionHandler offerActionHandler = new OfferActionHandler() {
@Override
public void onCreateOffer(TradeCurrency tradeCurrency) {
if (!createOfferViewOpen) {
OfferView.this.createOfferViewOpen = true;
OfferView.this.tradeCurrency = tradeCurrency;
OfferView.this.navigation.navigateTo(MainView.class, OfferView.this.getClass(),
CreateOfferView.class);
} else {
new Popup().information("You have already a \"Create offer\" tab open.").show();
}
}
@Override
public void onTakeOffer(Offer offer) {
if (!takeOfferViewOpen) {
OfferView.this.takeOfferViewOpen = true;
OfferView.this.offer = offer;
OfferView.this.navigation.navigateTo(MainView.class, OfferView.this.getClass(),
TakeOfferView.class);
} else {
new Popup().information("You have already a \"Take offer\" tab open.").show();
}
}
};
offerBookView.setOfferActionHandler(offerActionHandler);
offerBookView.setDirection(direction);
} else if (viewClass == CreateOfferView.class && createOfferView == null) {
view = viewLoader.load(viewClass);
// CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times
// in different graphs
createOfferView = (CreateOfferView) view;
createOfferView.initWithData(direction, tradeCurrency);
createOfferPane = createOfferView.getRoot();
createOfferTab = new Tab(getCreateOfferTabName());
// close handler from close on create offer action
createOfferView.setCloseHandler(() -> tabPane.getTabs().remove(createOfferTab));
createOfferTab.setContent(createOfferPane);
tabPane.getTabs().add(createOfferTab);
tabPane.getSelectionModel().select(createOfferTab);
} else if (viewClass == TakeOfferView.class && takeOfferView == null && offer != null) {
view = viewLoader.load(viewClass);
// CreateOffer and TakeOffer must not be cached by ViewLoader as we cannot use a view multiple times
// in different graphs
takeOfferView = (TakeOfferView) view;
takeOfferView.initWithData(offer);
takeOfferPane = ((TakeOfferView) view).getRoot();
takeOfferTab = new Tab(getTakeOfferTabName());
// close handler from close on take offer action
takeOfferView.setCloseHandler(() -> tabPane.getTabs().remove(takeOfferTab));
takeOfferTab.setContent(takeOfferPane);
tabPane.getTabs().add(takeOfferTab);
tabPane.getSelectionModel().select(takeOfferTab);
}
}
protected abstract String getCreateOfferTabName();
protected abstract String getTakeOfferTabName();
private void onCreateOfferViewRemoved() {
createOfferViewOpen = false;
if (createOfferView != null) {
createOfferView.onClose();
createOfferView = null;
}
offerBookView.enableCreateOfferButton();
// update the navigation state
navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class);
}
private void onTakeOfferViewRemoved() {
offer = null;
takeOfferViewOpen = false;
if (takeOfferView != null) {
takeOfferView.onClose();
takeOfferView = null;
}
// update the navigation state
navigation.navigateTo(MainView.class, this.getClass(), OfferBookView.class);
}
public interface OfferActionHandler {
void onCreateOffer(TradeCurrency tradeCurrency);
void onTakeOffer(Offer offer);
}
public interface CloseHandler {
void close();
}
}