implement items edit table
This commit is contained in:
@@ -0,0 +1,101 @@
|
|||||||
|
package ru.trader.db.controllers;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.TableColumn;
|
||||||
|
import javafx.scene.control.TableView;
|
||||||
|
import javafx.scene.control.cell.ComboBoxTableCell;
|
||||||
|
import ru.trader.controllers.MainController;
|
||||||
|
import ru.trader.controllers.Screeners;
|
||||||
|
import ru.trader.core.FACTION;
|
||||||
|
import ru.trader.core.GOVERNMENT;
|
||||||
|
import ru.trader.model.GroupModel;
|
||||||
|
import ru.trader.model.ItemModel;
|
||||||
|
import ru.trader.model.MarketModel;
|
||||||
|
import ru.trader.model.support.ChangeMarketListener;
|
||||||
|
import ru.trader.view.support.FactionStringConverter;
|
||||||
|
import ru.trader.view.support.GovernmentStringConverter;
|
||||||
|
import ru.trader.view.support.Localization;
|
||||||
|
import ru.trader.view.support.ViewUtils;
|
||||||
|
import ru.trader.view.support.cells.CheckComboBoxTableCell;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ItemsController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableView<ItemModel> tblItems;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<ItemModel, GroupModel> group;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<ItemModel, Collection<FACTION>> factions;
|
||||||
|
@FXML
|
||||||
|
private TableColumn<ItemModel, Collection<GOVERNMENT>> governments;
|
||||||
|
|
||||||
|
private ObservableList<ItemModel> items = FXCollections.observableArrayList();
|
||||||
|
private ObservableList<GroupModel> groups = FXCollections.observableArrayList();
|
||||||
|
private MarketModel world = null;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void initialize() {
|
||||||
|
tblItems.setItems(items);
|
||||||
|
group.setCellFactory(ComboBoxTableCell.forTableColumn(groups));
|
||||||
|
factions.setCellFactory(CheckComboBoxTableCell.forTableColumn(factions,
|
||||||
|
FXCollections.observableArrayList(FACTION.values()), new FactionStringConverter(), ItemModel::setIllegal)
|
||||||
|
);
|
||||||
|
governments.setCellFactory(CheckComboBoxTableCell.forTableColumn(governments,
|
||||||
|
FXCollections.observableArrayList(GOVERNMENT.values()), new GovernmentStringConverter(), ItemModel::setIllegal)
|
||||||
|
);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(){
|
||||||
|
if (world != null) world.getNotificator().remove(marketChangeListener);
|
||||||
|
world = MainController.getWorld();
|
||||||
|
world.getNotificator().add(marketChangeListener);
|
||||||
|
items.clear();
|
||||||
|
items.addAll(world.itemsProperty());
|
||||||
|
groups.clear();
|
||||||
|
groups.addAll(world.getGroups());
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void add(){
|
||||||
|
Screeners.showAddItem(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void remove(){
|
||||||
|
ItemModel item = tblItems.getSelectionModel().getSelectedItem();
|
||||||
|
if (item != null){
|
||||||
|
remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void remove(ItemModel item){
|
||||||
|
Optional<ButtonType> res = Screeners.showConfirm(String.format(Localization.getString("dialog.confirm.remove"), item.getName()));
|
||||||
|
if (res.isPresent() && res.get() == ButtonType.YES) {
|
||||||
|
world.remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private final ChangeMarketListener marketChangeListener = new ChangeMarketListener() {
|
||||||
|
@Override
|
||||||
|
public void add(ItemModel item) {
|
||||||
|
ViewUtils.doFX(() -> {
|
||||||
|
ItemsController.this.items.add(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove(ItemModel item) {
|
||||||
|
ViewUtils.doFX(() -> {
|
||||||
|
ItemsController.this.items.remove(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,10 +3,13 @@ package ru.trader.model;
|
|||||||
import javafx.beans.property.*;
|
import javafx.beans.property.*;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ru.trader.core.FACTION;
|
||||||
|
import ru.trader.core.GOVERNMENT;
|
||||||
import ru.trader.core.Item;
|
import ru.trader.core.Item;
|
||||||
import ru.trader.core.OFFER_TYPE;
|
import ru.trader.core.OFFER_TYPE;
|
||||||
import ru.trader.view.support.Localization;
|
import ru.trader.view.support.Localization;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ItemModel implements Comparable<ItemModel> {
|
public class ItemModel implements Comparable<ItemModel> {
|
||||||
@@ -113,6 +116,26 @@ public class ItemModel implements Comparable<ItemModel> {
|
|||||||
return item.getGroup() != null && item.getGroup().isMarket();
|
return item.getGroup() != null && item.getGroup().isMarket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<FACTION> getIllegalFactions(){
|
||||||
|
return item.getIllegalFactions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIllegalFactions(Collection<FACTION> factions){
|
||||||
|
LOG.debug("Set illegal factions {}", factions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIllegal(FACTION faction, boolean illegal){
|
||||||
|
item.setIllegal(faction, illegal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<GOVERNMENT> getIllegalGovernments(){
|
||||||
|
return item.getIllegalGovernments();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIllegal(GOVERNMENT government, boolean illegal){
|
||||||
|
item.setIllegal(government, illegal);
|
||||||
|
}
|
||||||
|
|
||||||
public void refresh(){
|
public void refresh(){
|
||||||
LOG.trace("Refresh stats of itemDesc {}", this);
|
LOG.trace("Refresh stats of itemDesc {}", this);
|
||||||
statBuy.refresh();
|
statBuy.refresh();
|
||||||
|
|||||||
@@ -162,6 +162,13 @@ public class MarketModel {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void remove(ItemModel item) {
|
||||||
|
LOG.info("Remove item {} from market {}", item, this);
|
||||||
|
market.remove(ModelFabric.get(item));
|
||||||
|
notificator.sendRemove(item);
|
||||||
|
items.remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
ItemStat getStat(OFFER_TYPE type, Item item){
|
ItemStat getStat(OFFER_TYPE type, Item item){
|
||||||
return market.getStat(type, item);
|
return market.getStat(type, item);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package ru.trader.view.support.cells;
|
||||||
|
|
||||||
|
|
||||||
|
import impl.org.controlsfx.skin.CheckComboBoxSkin;
|
||||||
|
import javafx.beans.value.ChangeListener;
|
||||||
|
import javafx.collections.ListChangeListener;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.scene.control.*;
|
||||||
|
import javafx.util.Callback;
|
||||||
|
import javafx.util.StringConverter;
|
||||||
|
import org.controlsfx.control.CheckComboBox;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class CheckComboBoxTableCell<S,T> extends TableCell<S, Collection<T>> {
|
||||||
|
private final CheckComboBox<T> box;
|
||||||
|
private final ChangeListener<Boolean> onShowListener;
|
||||||
|
private ComboBox comboBox;
|
||||||
|
|
||||||
|
public CheckComboBoxTableCell(final TableColumn<S, Collection<T>> column, final ObservableList<T> choiceList, final StringConverter<T> converter, final CheckedFunction<S, T> onCheckFunction) {
|
||||||
|
box = new CheckComboBox<>(choiceList);
|
||||||
|
box.setConverter(converter);
|
||||||
|
box.disableProperty().bind(column.editableProperty().not());
|
||||||
|
|
||||||
|
onShowListener = (ov, o, n) -> {
|
||||||
|
final TableView<S> tableView = getTableView();
|
||||||
|
if (n && !isEditing()) {
|
||||||
|
tableView.getSelectionModel().select(getTableRow().getIndex());
|
||||||
|
tableView.edit(tableView.getSelectionModel().getSelectedIndex(), column);
|
||||||
|
} else {
|
||||||
|
if (!n && isEditing()) {
|
||||||
|
cancelEdit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
box.skinProperty().addListener(e -> {
|
||||||
|
if (comboBox != null){
|
||||||
|
comboBox.showingProperty().removeListener(onShowListener);
|
||||||
|
}
|
||||||
|
comboBox = getComboBox(box);
|
||||||
|
if (comboBox != null) {
|
||||||
|
comboBox.showingProperty().addListener(onShowListener);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Don't found ComboBox in checkComboBox");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
box.getCheckModel().getCheckedItems().addListener((ListChangeListener<T>) c -> {
|
||||||
|
if (isEditing()){
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
S entry = (S) getTableRow().getItem();
|
||||||
|
if (entry != null){
|
||||||
|
while (c.next()) {
|
||||||
|
if (c.wasAdded())
|
||||||
|
for (T item : c.getAddedSubList()) {
|
||||||
|
onCheckFunction.apply(entry, item, true);
|
||||||
|
} else if (c.wasRemoved()){
|
||||||
|
for (T item : c.getRemoved()) {
|
||||||
|
onCheckFunction.apply(entry, item, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <S,T> Callback<TableColumn<S,Collection<T>>, TableCell<S,Collection<T>>> forTableColumn(final TableColumn<S, Collection<T>> column, final ObservableList<T> choiceList, final StringConverter<T> converter, final CheckedFunction<S, T> onCheckFunction) {
|
||||||
|
return cell -> new CheckComboBoxTableCell<>(column, choiceList, converter, onCheckFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateItem(Collection<T> items, boolean empty) {
|
||||||
|
super.updateItem(items, empty);
|
||||||
|
|
||||||
|
setText(null);
|
||||||
|
if (empty || items == null) {
|
||||||
|
setGraphic(null);
|
||||||
|
} else {
|
||||||
|
checkAll(items);
|
||||||
|
setGraphic(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAll(Collection<T> items){
|
||||||
|
box.getCheckModel().clearChecks();
|
||||||
|
for (T item : items) {
|
||||||
|
box.getCheckModel().check(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static ComboBox getComboBox(CheckComboBox box){
|
||||||
|
Skin skin = box.getSkin();
|
||||||
|
if (skin instanceof CheckComboBoxSkin){
|
||||||
|
Optional node = ((CheckComboBoxSkin) skin).getChildren().stream().findFirst();
|
||||||
|
if (node.isPresent() && node.get() instanceof ComboBox){
|
||||||
|
return (ComboBox) node.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CheckedFunction<S, T> {
|
||||||
|
|
||||||
|
void apply(S entry, T item, boolean check);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
43
client/src/main/resources/view/db/items.fxml
Normal file
43
client/src/main/resources/view/db/items.fxml
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.control.cell.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
|
||||||
|
|
||||||
|
<?import ru.trader.view.support.cells.OfferCellValueImpl?>
|
||||||
|
<?import ru.trader.view.support.cells.DoubleCell?>
|
||||||
|
|
||||||
|
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="ru.trader.db.controllers.ItemsController">
|
||||||
|
<TableView fx:id="tblItems" editable="true" VBox.vgrow="ALWAYS" prefWidth="800">
|
||||||
|
<columns>
|
||||||
|
<TableColumn minWidth="120" text="ID">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="id"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn minWidth="200" text="%market.item.name">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="name"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn fx:id="group" minWidth="120" text="Группа" editable="false">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="group"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn fx:id="factions" minWidth="145" text="Запрещено в">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="illegalFactions"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
<TableColumn fx:id="governments" minWidth="145" text="Запрещено в">
|
||||||
|
<cellValueFactory><PropertyValueFactory property="illegalGovernments"/></cellValueFactory>
|
||||||
|
</TableColumn>
|
||||||
|
</columns>
|
||||||
|
<columnResizePolicy>
|
||||||
|
<TableView fx:constant="UNCONSTRAINED_RESIZE_POLICY"/>
|
||||||
|
</columnResizePolicy>
|
||||||
|
<contextMenu>
|
||||||
|
<ContextMenu>
|
||||||
|
<items>
|
||||||
|
<MenuItem text="Добавить" onAction="#add" />
|
||||||
|
<MenuItem text="Удалить" onAction="#remove" />
|
||||||
|
</items>
|
||||||
|
</ContextMenu>
|
||||||
|
</contextMenu>
|
||||||
|
</TableView>
|
||||||
|
</VBox>
|
||||||
@@ -104,6 +104,16 @@ public class SimpleMarket extends AbstractMarket {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void removeItem(Item item) {
|
protected void removeItem(Item item) {
|
||||||
|
ItemStat stat = sellItems.get(item);
|
||||||
|
for (Offer offer : stat.getOffers()) {
|
||||||
|
SimpleVendor vendor = (SimpleVendor) offer.getVendor();
|
||||||
|
vendor.removeOffer(offer);
|
||||||
|
}
|
||||||
|
stat = buyItems.get(item);
|
||||||
|
for (Offer offer : stat.getOffers()) {
|
||||||
|
SimpleVendor vendor = (SimpleVendor) offer.getVendor();
|
||||||
|
vendor.removeOffer(offer);
|
||||||
|
}
|
||||||
items.remove(item);
|
items.remove(item);
|
||||||
sellItems.remove(item);
|
sellItems.remove(item);
|
||||||
buyItems.remove(item);
|
buyItems.remove(item);
|
||||||
|
|||||||
Reference in New Issue
Block a user