From da689e1d3afe2532f881312a1c514d25160d32d9 Mon Sep 17 00:00:00 2001 From: Mo Date: Wed, 6 Jan 2016 14:47:28 +0300 Subject: [PATCH] implement vendor filter edit dialog --- client/src/main/java/ru/trader/Main.java | 1 + .../trader/controllers/FilterController.java | 77 ++++++++- .../java/ru/trader/controllers/Screeners.java | 20 +++ .../controllers/VendorFilterController.java | 158 ++++++++++++++++++ .../main/java/ru/trader/model/GroupModel.java | 15 ++ .../main/java/ru/trader/model/ItemModel.java | 4 + client/src/main/resources/view/filter.fxml | 21 ++- client/src/main/resources/view/vFilter.fxml | 24 +++ .../java/ru/trader/core/MarketFilter.java | 23 ++- .../java/ru/trader/core/VendorFilter.java | 26 ++- 10 files changed, 358 insertions(+), 11 deletions(-) create mode 100644 client/src/main/java/ru/trader/controllers/VendorFilterController.java create mode 100644 client/src/main/resources/view/vFilter.fxml diff --git a/client/src/main/java/ru/trader/Main.java b/client/src/main/java/ru/trader/Main.java index df4a25f..cf2022c 100644 --- a/client/src/main/java/ru/trader/Main.java +++ b/client/src/main/java/ru/trader/Main.java @@ -117,6 +117,7 @@ public class Main extends Application { Screeners.loadGroupAddStage(getUrl("groupAdd.fxml")); Screeners.loadLoginStage(getUrl("login.fxml")); Screeners.loadHelperStage(getUrl("helper.fxml")); + Screeners.loadVendorFilterStage(getUrl("vFilter.fxml")); } private static URL getUrl(String filename) throws MalformedURLException { diff --git a/client/src/main/java/ru/trader/controllers/FilterController.java b/client/src/main/java/ru/trader/controllers/FilterController.java index 3058bf6..1ea63ee 100644 --- a/client/src/main/java/ru/trader/controllers/FilterController.java +++ b/client/src/main/java/ru/trader/controllers/FilterController.java @@ -1,12 +1,15 @@ package ru.trader.controllers; +import javafx.collections.FXCollections; import javafx.fxml.FXML; import javafx.scene.Parent; import javafx.scene.control.*; +import javafx.util.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ru.trader.core.MarketFilter; import ru.trader.core.SERVICE_TYPE; +import ru.trader.core.VendorFilter; import ru.trader.model.MarketModel; import ru.trader.model.ModelFabric; import ru.trader.model.StationModel; @@ -19,6 +22,7 @@ import ru.trader.view.support.autocomplete.CachedSuggestionProvider; import ru.trader.view.support.autocomplete.SystemsProvider; import ru.trader.view.support.cells.CustomListCell; +import java.util.Map; import java.util.Optional; public class FilterController { @@ -56,6 +60,14 @@ public class FilterController { private CheckBox cbLargeLandpad; @FXML private ListView excludes; + @FXML + private TextField vFilterSystemText; + private AutoCompletion vFilterSystem; + @FXML + private ComboBox vFilterStation; + @FXML + private ListView> vFilters; + private MarketModel market; private MarketFilter filter; @@ -64,11 +76,17 @@ public class FilterController { @FXML private void initialize(){ init(); - excludes.setCellFactory(new CustomListCell<>(s -> String.format("%s (%s)", s.getSystem().getName(), s.getName()))); + excludes.setCellFactory(new CustomListCell<>(StationModel::getFullName)); system.valueProperty().addListener((ov, o, n) -> { station.setItems(n.getStationNamesList()); station.getSelectionModel().selectFirst(); }); + vFilterSystem.valueProperty().addListener((ov, o, n) -> { + vFilterStation.setItems(n.getStationNamesList()); + vFilterStation.getSelectionModel().selectFirst(); + }); + vFilters.setCellFactory(new CustomListCell<>(Pair::getKey)); + vFilters.setItems(FXCollections.observableArrayList()); } void init(){ @@ -86,6 +104,12 @@ public class FilterController { center.setSuggestions(provider.getPossibleSuggestions()); center.setConverter(provider.getConverter()); } + if (vFilterSystem == null){ + vFilterSystem = new AutoCompletion<>(vFilterSystemText, new CachedSuggestionProvider<>(provider), ModelFabric.NONE_SYSTEM, provider.getConverter()); + } else { + vFilterSystem.setSuggestions(provider.getPossibleSuggestions()); + vFilterSystem.setConverter(provider.getConverter()); + } } private void createDialog(Parent owner, Parent content){ @@ -120,6 +144,10 @@ public class FilterController { cbMediumLandpad.setSelected(filter.has(SERVICE_TYPE.MEDIUM_LANDPAD)); cbLargeLandpad.setSelected(filter.has(SERVICE_TYPE.LARGE_LANDPAD)); excludes.setItems(BindingsHelper.observableList(filter.getExcludes(), market.getModeler()::get)); + vFilters.getItems().clear(); + for (Map.Entry entry : filter.getVendorFilters().entrySet()) { + vFilters.getItems().add(new Pair<>(entry.getKey(), entry.getValue())); + } } private void clear(){ @@ -127,7 +155,8 @@ public class FilterController { center.setValue(ModelFabric.NONE_SYSTEM); radius.clear(); distance.clear(); - excludes.getItems().clear(); + excludes.setItems(FXCollections.emptyObservableList()); + vFilters.getItems().clear(); } private void save() { @@ -147,6 +176,8 @@ public class FilterController { if (cbLargeLandpad.isSelected()) filter.add(SERVICE_TYPE.LARGE_LANDPAD); else filter.remove(SERVICE_TYPE.LARGE_LANDPAD); filter.clearExcludes(); excludes.getItems().forEach(st -> filter.addExclude(ModelFabric.get(st))); + filter.clearVendorFilters(); + vFilters.getItems().forEach(f -> filter.addFilter(f.getKey(), f.getValue())); LOG.trace("New filter", filter); } @@ -194,4 +225,46 @@ public class FilterController { excludes.getItems().clear(); } + @FXML + private void addVendorFilter() { + SystemModel s = vFilterSystem.getValue(); + if (s != null){ + StationModel st = s.get(vFilterStation.getValue()); + if (!ModelFabric.isFake(st)){ + Optional filter = Screeners.showVendorFilter(); + if (filter.isPresent()) { + String key = MarketFilter.getVendorKey(ModelFabric.get(st)); + vFilters.getItems().add(new Pair<>(key, filter.get())); + } + } + } + } + + @FXML + private void editVendorFilter() { + int index = vFilters.getSelectionModel().getSelectedIndex(); + if (index >= 0){ + VendorFilter filter = vFilters.getItems().get(index).getValue(); + Screeners.showFilter(filter); + } + } + + @FXML + private void removeVendorFilter() { + int index = vFilters.getSelectionModel().getSelectedIndex(); + if (index >= 0){ + vFilters.getItems().remove(index); + } + } + + @FXML + private void cleanVendorFilters() { + vFilters.getItems().clear(); + } + + @FXML + private void editDefaultVendorFilter() { + Screeners.showFilter(filter.getDefaultVendorFilter()); + } + } diff --git a/client/src/main/java/ru/trader/controllers/Screeners.java b/client/src/main/java/ru/trader/controllers/Screeners.java index dd9de9e..234f80a 100644 --- a/client/src/main/java/ru/trader/controllers/Screeners.java +++ b/client/src/main/java/ru/trader/controllers/Screeners.java @@ -13,6 +13,7 @@ import org.controlsfx.control.action.Action; import org.controlsfx.dialog.Dialogs; import ru.trader.EMDNUpdater; import ru.trader.core.MarketFilter; +import ru.trader.core.VendorFilter; import ru.trader.model.*; import ru.trader.view.support.CustomBuilderFactory; import ru.trader.view.support.Localization; @@ -35,6 +36,7 @@ public class Screeners { private static Parent groupAddScreen; private static Parent loginScreen; private static Parent helperScreen; + private static Parent vFilterScreen; private static MainController mainController; private static ItemDescController itemDescController; @@ -48,6 +50,7 @@ public class Screeners { private static GroupAddController groupAddController; private static LoginController loginController; private static HelperController helperController; + private static VendorFilterController vFilterController; private static FXMLLoader initLoader(URL url){ FXMLLoader loader = new FXMLLoader(url, Localization.getResources()); @@ -151,6 +154,13 @@ public class Screeners { helperController = loader.getController(); } + public static void loadVendorFilterStage(URL fxml) throws IOException { + FXMLLoader loader = initLoader(fxml); + vFilterScreen = loader.load(); + addStylesheet(vFilterScreen); + vFilterController = loader.getController(); + } + public static void show(Node node){ mainController.getMainPane().setCenter(node); } @@ -272,10 +282,20 @@ public class Screeners { systemsEditorController.init(); vEditorController.init(); filterController.init(); + vFilterController.init(); EMDNUpdater.setMarket(MainController.getMarket()); } public static void showTrackTab(){ mainController.showTrack(); } + + public static Optional showVendorFilter() { + return vFilterController.showDialog(mainScreen, vFilterScreen); + } + + public static boolean showFilter(VendorFilter filter) { + return vFilterController.showEditDialog(mainScreen, vFilterScreen, filter); + } + } diff --git a/client/src/main/java/ru/trader/controllers/VendorFilterController.java b/client/src/main/java/ru/trader/controllers/VendorFilterController.java new file mode 100644 index 0000000..84e870d --- /dev/null +++ b/client/src/main/java/ru/trader/controllers/VendorFilterController.java @@ -0,0 +1,158 @@ +package ru.trader.controllers; + +import javafx.fxml.FXML; +import javafx.scene.Parent; +import javafx.scene.control.ButtonBar; +import javafx.scene.control.ButtonType; +import javafx.scene.control.CheckBox; +import javafx.scene.control.Dialog; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.trader.core.Item; +import ru.trader.core.VendorFilter; +import ru.trader.model.GroupModel; +import ru.trader.model.ItemModel; +import ru.trader.model.MarketModel; +import ru.trader.model.ModelFabric; +import ru.trader.view.support.Localization; + +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; + +public class VendorFilterController { + private final static Logger LOG = LoggerFactory.getLogger(VendorFilterController.class); + + @FXML + private GridPane sellCbs; + @FXML + private GridPane buyCbs; + @FXML + private CheckBox cbDontSell; + @FXML + private CheckBox cbDontBuy; + @FXML + private CheckBox cbSkipIllegal; + + private VendorFilter filter; + private Dialog dlg; + + @FXML + private void initialize(){ + init(); + } + + void init(){ + MarketModel market = MainController.getMarket(); + sellCbs.getChildren().clear(); + buyCbs.getChildren().clear(); + initCheckboxes(market.itemsProperty().filtered(ItemModel::isMarketItem)); + + } + + private void initCheckboxes(Collection items){ + int column = -1; + int row = -1; + GroupModel currentGroup = null; + for (ItemModel item : items) { + row++; + if (column == -1 || !Objects.equals(currentGroup, item.getGroup())){ + column++; + row = 0; + currentGroup = item.getGroup(); + } + CheckBox cb = new CheckBox(item.getName()); + cb.setUserData(item); + sellCbs.add(cb, column, row); + cb = new CheckBox(item.getName()); + cb.setUserData(item); + buyCbs.add(cb, column, row); + } + + } + + private void createDialog(Parent owner, Parent content){ + dlg = new Dialog<>(); + if (owner != null) dlg.initOwner(owner.getScene().getWindow()); + dlg.setTitle(Localization.getString("filter.title")); + ButtonType saveButton = new ButtonType(Localization.getString("dialog.button.save"), ButtonBar.ButtonData.OK_DONE); + dlg.getDialogPane().setContent(content); + dlg.getDialogPane().getButtonTypes().addAll(saveButton, ButtonType.CANCEL); + dlg.setResultConverter(dialogButton -> { + if (dialogButton == saveButton) { + save(); + return this.filter; + } + return null; + }); + dlg.setResizable(false); + } + + private void fill(VendorFilter filter){ + this.filter = filter; + cbSkipIllegal.setSelected(filter.isSkipIllegal()); + cbDontSell.setSelected(filter.isDontSell()); + cbDontBuy.setSelected(filter.isDontBuy()); + fillCheckboxes(sellCbs, filter.getSellExcludes()); + fillCheckboxes(buyCbs, filter.getBuyExcludes()); + } + + private void fillCheckboxes(Pane checkboxes, Collection excludes) { + checkboxes.getChildren().stream().filter(node -> node instanceof CheckBox).forEach(node -> { + CheckBox checkbox = (CheckBox) node; + ItemModel item = (ItemModel) checkbox.getUserData(); + if (item != null) { + checkbox.setSelected(excludes.contains(ModelFabric.get(item))); + } + }); + } + + private void clear(){ + this.filter = null; + } + + private void save() { + LOG.trace("Old filter", filter); + filter.setSkipIllegal(cbSkipIllegal.isSelected()); + filter.dontSell(cbDontSell.isSelected()); + filter.dontBuy(cbDontBuy.isSelected()); + filter.clearSellExcludes(); + sellCbs.getChildren().stream().filter(node -> node instanceof CheckBox).forEach(node -> { + CheckBox checkbox = (CheckBox) node; + ItemModel item = (ItemModel) checkbox.getUserData(); + if (item != null) { + if (checkbox.isSelected()) filter.addSellExclude(ModelFabric.get(item)); + } + }); + filter.clearBuyExcludes(); + buyCbs.getChildren().stream().filter(node -> node instanceof CheckBox).forEach(node -> { + CheckBox checkbox = (CheckBox) node; + ItemModel item = (ItemModel) checkbox.getUserData(); + if (item != null) { + if (checkbox.isSelected()) filter.addBuyExclude(ModelFabric.get(item)); + } + }); + LOG.trace("New filter", filter); + } + + public Optional showDialog(Parent parent, Parent content){ + return showDialog(parent, content, new VendorFilter()); + } + + public boolean showEditDialog(Parent parent, Parent content, VendorFilter filter){ + return showDialog(parent, content, filter).isPresent(); + } + + private Optional showDialog(Parent parent, Parent content, VendorFilter filter){ + if (dlg == null){ + createDialog(parent, content); + } + fill(filter); + Optional result = dlg.showAndWait(); + clear(); + return result; + } + +} diff --git a/client/src/main/java/ru/trader/model/GroupModel.java b/client/src/main/java/ru/trader/model/GroupModel.java index 706a084..dd21a3a 100644 --- a/client/src/main/java/ru/trader/model/GroupModel.java +++ b/client/src/main/java/ru/trader/model/GroupModel.java @@ -6,6 +6,8 @@ import javafx.beans.property.StringProperty; import ru.trader.core.Group; import ru.trader.view.support.Localization; +import java.util.Objects; + public class GroupModel implements Comparable { private final Group group; @@ -52,6 +54,19 @@ public class GroupModel implements Comparable { return getName().compareTo(other.getName()); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GroupModel that = (GroupModel) o; + return Objects.equals(group, that.group); + } + + @Override + public int hashCode() { + return Objects.hash(group); + } + @Override public String toString() { return getName(); diff --git a/client/src/main/java/ru/trader/model/ItemModel.java b/client/src/main/java/ru/trader/model/ItemModel.java index a7d2a34..40f5d5c 100644 --- a/client/src/main/java/ru/trader/model/ItemModel.java +++ b/client/src/main/java/ru/trader/model/ItemModel.java @@ -65,6 +65,10 @@ public class ItemModel implements Comparable { } } + public GroupModel getGroup(){ + return group; + } + public ReadOnlyDoubleProperty avgBuyProperty() { return statBuy.avgProperty(); } diff --git a/client/src/main/resources/view/filter.fxml b/client/src/main/resources/view/filter.fxml index c8e1270..eedb522 100644 --- a/client/src/main/resources/view/filter.fxml +++ b/client/src/main/resources/view/filter.fxml @@ -1,12 +1,12 @@ - + - +