Archived
0

implement vendor filter edit dialog

This commit is contained in:
Mo
2016-01-06 14:47:28 +03:00
parent 47d6284d83
commit da689e1d3a
10 changed files with 358 additions and 11 deletions

View File

@@ -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 {

View File

@@ -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<StationModel> excludes;
@FXML
private TextField vFilterSystemText;
private AutoCompletion<SystemModel> vFilterSystem;
@FXML
private ComboBox<String> vFilterStation;
@FXML
private ListView<Pair<String, VendorFilter>> 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<String, VendorFilter> 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<VendorFilter> 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());
}
}

View File

@@ -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<VendorFilter> showVendorFilter() {
return vFilterController.showDialog(mainScreen, vFilterScreen);
}
public static boolean showFilter(VendorFilter filter) {
return vFilterController.showEditDialog(mainScreen, vFilterScreen, filter);
}
}

View File

@@ -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<VendorFilter> 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<ItemModel> 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<Item> 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<VendorFilter> 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<VendorFilter> showDialog(Parent parent, Parent content, VendorFilter filter){
if (dlg == null){
createDialog(parent, content);
}
fill(filter);
Optional<VendorFilter> result = dlg.showAndWait();
clear();
return result;
}
}

View File

@@ -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<GroupModel> {
private final Group group;
@@ -52,6 +54,19 @@ public class GroupModel implements Comparable<GroupModel> {
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();

View File

@@ -65,6 +65,10 @@ public class ItemModel implements Comparable<ItemModel> {
}
}
public GroupModel getGroup(){
return group;
}
public ReadOnlyDoubleProperty avgBuyProperty() {
return statBuy.avgProperty();
}

View File

@@ -1,12 +1,12 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import org.controlsfx.glyphfont.Glyph?>
<?import org.controlsfx.glyphfont.*?>
<?import ru.trader.view.support.NumberField?>
<GridPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ru.trader.controllers.FilterController"
styleClass="dialog" vgap="4" hgap="8">
<columnConstraints>
<ColumnConstraints minWidth="180" maxWidth="180"/>
<ColumnConstraints minWidth="250" maxWidth="250"/>
<ColumnConstraints minWidth="320" maxWidth="320"/>
</columnConstraints>
<Label text="%filter.title" styleClass="settings-group" GridPane.halignment="CENTER" GridPane.columnSpan="2"/>
<Label text="%filter.center" GridPane.rowIndex="1"/>
@@ -37,7 +37,22 @@
<Button prefWidth="30" onAction="#clean"><graphic><Glyph text="FontAwesome|TRASH_ALT"/></graphic></Button>
</HBox>
</VBox>
<ListView fx:id="excludes" GridPane.rowIndex="6" GridPane.columnIndex="1" maxHeight="200"/>
<ListView fx:id="excludes" GridPane.rowIndex="6" GridPane.columnIndex="1" maxHeight="120"/>
<Label text="Фильтры на товары:" GridPane.rowIndex="7" />
<VBox GridPane.rowIndex="8" spacing="4">
<TextField fx:id="vFilterSystemText" minWidth="180"/>
<ComboBox fx:id="vFilterStation" minWidth="180"/>
<HBox spacing="2" alignment="BASELINE_RIGHT">
<Button prefWidth="30" onAction="#addVendorFilter"><graphic><Glyph text="FontAwesome|PLUS"/></graphic></Button>
<Button prefWidth="30" onAction="#editVendorFilter"><graphic><Glyph text="FontAwesome|EDIT"/></graphic></Button>
<Button prefWidth="30" onAction="#removeVendorFilter"><graphic><Glyph text="FontAwesome|MINUS"/></graphic></Button>
<Button prefWidth="30" onAction="#cleanVendorFilters"><graphic><Glyph text="FontAwesome|TRASH_ALT"/></graphic></Button>
</HBox>
<Button prefWidth="180" text="Глобальный фильтр" onAction="#editDefaultVendorFilter"/>
</VBox>
<ListView fx:id="vFilters" GridPane.rowIndex="8" GridPane.columnIndex="1" maxHeight="120"/>
</GridPane>

View File

@@ -0,0 +1,24 @@
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ru.trader.controllers.VendorFilterController"
styleClass="dialog" spacing="10">
<HBox spacing="10">
<CheckBox fx:id="cbSkipIllegal" text="Только легальные"/>
<CheckBox fx:id="cbDontSell" text="Не покупать"/>
<CheckBox fx:id="cbDontBuy" text="Не продавать"/>
</HBox>
<VBox spacing="4">
<Label text="Не покупать:"/>
<ScrollPane maxHeight="200" maxWidth="400">
<GridPane fx:id="sellCbs" hgap="5" vgap="5"/>
</ScrollPane>
</VBox>
<VBox spacing="4">
<Label text="Не продавать:"/>
<ScrollPane maxHeight="200" maxWidth="400">
<GridPane fx:id="buyCbs" hgap="5" vgap="5"/>
</ScrollPane>
</VBox>
</VBox>

View File

@@ -2,7 +2,6 @@ package ru.trader.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.analysis.FilteredVendor;
import java.util.*;
@@ -84,23 +83,43 @@ public class MarketFilter {
return excludes;
}
private String getVendorKey(Vendor vendor){
public static String getVendorKey(Vendor vendor){
return vendor == null ? null : vendor.getFullName();
}
public VendorFilter getDefaultVendorFilter() {
return defaultVendorFilter;
}
public Map<String, VendorFilter> getVendorFilters() {
return customFilteredVendors;
}
public void addFilter(Vendor vendor, VendorFilter vendorFilter){
customFilteredVendors.put(getVendorKey(vendor), vendorFilter);
}
public void addFilter(String key, VendorFilter vendorFilter){
customFilteredVendors.put(key, vendorFilter);
}
public void removeFilter(Vendor vendor){
customFilteredVendors.remove(getVendorKey(vendor));
}
public void removeFilter(String key){
customFilteredVendors.remove(key);
}
public VendorFilter getFilter(Vendor vendor){
VendorFilter filter = customFilteredVendors.get(getVendorKey(vendor));
return filter != null ? filter : defaultVendorFilter;
}
public void clearVendorFilters(){
customFilteredVendors.clear();
}
public boolean isFiltered(Place place){
return center != null && center.getDistance(place) > radius;
}

View File

@@ -11,6 +11,8 @@ public class VendorFilter {
private boolean disable;
private boolean skipIllegal;
private boolean dontBuy;
private boolean dontSell;
private final Collection<Item> buyExcludes;
private final Collection<Item> sellExcludes;
@@ -36,6 +38,22 @@ public class VendorFilter {
this.skipIllegal = skipIllegal;
}
public boolean isDontBuy() {
return dontBuy;
}
public void dontBuy(boolean dontBuy){
this.dontBuy = dontBuy;
}
public boolean isDontSell() {
return dontSell;
}
public void dontSell(boolean dontSell) {
this.dontSell = dontSell;
}
public void addBuyExclude(Item item){
buyExcludes.add(item);
}
@@ -72,8 +90,8 @@ public class VendorFilter {
if (disable) return false;
if (skipIllegal && offer.isIllegal()) return true;
switch (offer.getType()) {
case SELL: return sellExcludes.contains(offer.getItem());
case BUY: return buyExcludes.contains(offer.getItem());
case SELL: return dontSell || sellExcludes.contains(offer.getItem());
case BUY: return dontBuy || buyExcludes.contains(offer.getItem());
}
return false;
}
@@ -82,8 +100,8 @@ public class VendorFilter {
if (disable) return false;
if (skipIllegal && (item.isIllegal(vendor))) return true;
switch (offerType) {
case SELL: return sellExcludes.contains(item);
case BUY: return buyExcludes.contains(item);
case SELL: return dontSell || sellExcludes.contains(item);
case BUY: return dontBuy || buyExcludes.contains(item);
}
return false;
}