Archived
0

- add group item

- add color indication on edit offer
This commit is contained in:
iMoHax
2014-08-29 16:11:19 +04:00
parent 5db40e1a4f
commit fa77df4a7f
13 changed files with 393 additions and 148 deletions

View File

@@ -1,18 +1,25 @@
<?xml version="1.0" ?>
<market>
<items>
<group name="chemicals" type="MARKET">
<item name="explosives" id="i0"/>
<item name="hydrogenfuel" id="i1"/>
<item name="mineraloil" id="i2"/>
<item name="pesticides" id="i3"/>
</group>
<group name="consumer_items" type="MARKET">
<item name="clothing" id="i4"/>
<item name="consumertechnology" id="i5"/>
<item name="domesticappliances" id="i6"/>
</group>
<group name="drugs" type="MARKET">
<item name="beer" id="i7"/>
<item name="liquor" id="i8"/>
<item name="narcotics" id="i9"/>
<item name="tobacco" id="i10"/>
<item name="wine" id="i11"/>
</group>
<group name="foods" type="MARKET">
<item name="algae" id="i12"/>
<item name="animalmeat" id="i13"/>
<item name="coffee" id="i14"/>
@@ -22,19 +29,27 @@
<item name="grain" id="i19"/>
<item name="syntheticmeat" id="i20"/>
<item name="tea" id="i21"/>
</group>
<group name="industrial_materials" type="MARKET">
<item name="plastics" id="i23"/>
<item name="polymers" id="i24"/>
<item name="semiconductors" id="i25"/>
<item name="superconductors" id="i26"/>
</group>
<group name="machinery" type="MARKET">
<item name="cropharvesters" id="i27"/>
<item name="heliostaticfurnaces" id="i28"/>
<item name="marinesupplies" id="i29"/>
<item name="mineralextractors" id="i30"/>
</group>
<group name="medicines" type="MARKET">
<item name="agriculturalmedicines" id="i31"/>
<item name="basicmedicines" id="i32"/>
<item name="combatstabilisers" id="i33"/>
<item name="performanceenhancers" id="i34"/>
<item name="progenitorcells" id="i35"/>
</group>
<group name="metals" type="MARKET">
<item name="aluminium" id="i36"/>
<item name="copper" id="i37"/>
<item name="cobalt" id="i38"/>
@@ -46,6 +61,8 @@
<item name="titanium" id="i44"/>
<item name="silver" id="i45"/>
<item name="uranium" id="i46"/>
</group>
<group name="minerals" type="MARKET">
<item name="bauxite" id="i47"/>
<item name="bertrandite" id="i48"/>
<item name="beryllium" id="i49"/>
@@ -56,6 +73,8 @@
<item name="lepidolite" id="i54"/>
<item name="rutile" id="i55"/>
<item name="uraninite" id="i56"/>
</group>
<group name="technology" type="MARKET">
<item name="advancedcatalysers" id="i57"/>
<item name="animalmonitors" id="i58"/>
<item name="aquaponicsystems" id="i59"/>
@@ -66,14 +85,22 @@
<item name="resonatingseparators" id="i64"/>
<item name="robotics" id="i65"/>
<item name="terrainenrichmentsystems" id="i66"/>
</group>
<group name="textiles" type="MARKET">
<item name="leather" id="i68"/>
<item name="naturalfabrics" id="i69"/>
<item name="syntheticfabrics" id="i70"/>
</group>
<group name="waste" type="MARKET">
<item name="biowaste" id="i71"/>
<item name="scrap" id="i72"/>
</group>
<group name="weapons" type="MARKET">
<item name="nonlethalweapons" id="i73"/>
<item name="personalweapons" id="i74"/>
<item name="reactivearmour" id="i75"/>
</group>
<group name="ships" type="SHIP">
<item name="Sidewinder" id="i76"/>
<item name="Hauler" id="i77"/>
<item name="Eagle" id="i78"/>
@@ -82,6 +109,8 @@
<item name="TYPE-6" id="i81"/>
<item name="TYPE-9" id="i82"/>
<item name="Anaconda" id="i83"/>
</group>
<group name="pulselaser" type="OUTFIT">
<item name="Pulse Laser C1 (G)" id="i84"/>
<item name="Pulse Laser C1 (T)" id="i85"/>
<item name="Pulse Laser C2" id="i86"/>
@@ -90,9 +119,13 @@
<item name="Pulse Laser C4 (T)" id="i89"/>
<item name="Pulse Laser C5 (G)" id="i90"/>
<item name="Pulse Laser C6" id="i91"/>
</group>
<group name="burstlaser" type="OUTFIT">
<item name="Burst Laser C1 (G)" id="i92"/>
<item name="Burst Laser C2" id="i93"/>
<item name="Burst Laser C6" id="i94"/>
</group>
<group name="beamlaser" type="OUTFIT">
<item name="Beam Laser C1 (G)" id="i95"/>
<item name="Beam Laser C1 (T)" id="i96"/>
<item name="Beam Laser C2" id="i97"/>
@@ -101,28 +134,41 @@
<item name="Beam Laser C4" id="i99"/>
<item name="Beam Laser C4 (T)" id="i100"/>
<item name="Beam Laser C6" id="i101"/>
</group>
<group name="multicannon" type="OUTFIT">
<item name="Multicannon C1 (G)" id="i102"/>
<item name="Multicannon C2" id="i103"/>
<item name="Multicannon C2 (T)" id="i104"/>
<item name="Multicannon C3 (G)" id="i105"/>
<item name="Multicannon C4" id="i106"/>
</group>
<group name="cannon" type="OUTFIT">
<item name="Cannon C2" id="i107"/>
<item name="Cannon C4" id="i108"/>
<item name="Cannon C6" id="i109"/>
</group>
<group name="railgun" type="OUTFIT">
<item name="Rail Gun C2" id="i110"/>
<item name="Rail Gun C4" id="i111"/>
</group>
<group name="missile" type="OUTFIT">
<item name="Missile Rack C2" id="i112"/>
<item name="Missile Rack C4" id="i113"/>
</group>
<group name="alloy" type="OUTFIT">
<item name="Reinforced Alloy T6" id="i114"/>
<item name="Mirrored Surface Composite T6" id="i115"/>
<item name="Military Grade Composite T6" id="i116"/>
<item name="Reactive Surface Composite T6" id="i117"/>
</group>
<group name="module" type="OUTFIT">
<item name="Chaff Launcher" id="i118"/>
<item name="Point Defence Unit" id="i119"/>
<item name="Cargo Scanner" id="i120"/>
<item name="Heat Sink Launcher" id="i121"/>
<item name="Standart Docking Comp" id="i122"/>
<item name="Kill Warrant Scanner" id="i123"/>
</group>
</items>
<vendors>
<vendor name="26 Draconis" x="-39.0" y="-0.65625" z="24.90625"></vendor>

View File

@@ -1,5 +1,6 @@
package ru.trader.controllers;
import javafx.application.Platform;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleDoubleProperty;
@@ -12,6 +13,7 @@ import javafx.scene.control.TextField;
import org.controlsfx.control.ButtonBar;
import org.controlsfx.control.action.AbstractAction;
import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.DefaultDialogAction;
import org.controlsfx.dialog.Dialog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,7 +27,7 @@ import ru.trader.view.support.Localization;
import ru.trader.view.support.NumberField;
import ru.trader.view.support.PriceStringConverter;
import ru.trader.view.support.ViewUtils;
import ru.trader.view.support.cells.TextFieldCell;
import ru.trader.view.support.cells.EditOfferCell;
import java.util.Optional;
@@ -48,6 +50,18 @@ public class VendorEditorController {
}
};
private final Action actCancel = new DefaultDialogAction(impl.org.controlsfx.i18n.Localization.asKey("dlg.cancel.button")) {
{
ButtonBar.setType(this, ButtonBar.ButtonType.CANCEL_CLOSE);
}
@Override
public void handle(ActionEvent event) {
items.getSelectionModel().selectFirst();
super.handle(event);
}
};
@FXML
private TextField name;
@@ -69,8 +83,8 @@ public class VendorEditorController {
@FXML
private void initialize() {
items.getSelectionModel().setCellSelectionEnabled(true);
buy.setCellFactory(TextFieldCell.forTableColumn(new PriceStringConverter()));
sell.setCellFactory(TextFieldCell.forTableColumn(new PriceStringConverter()));
buy.setCellFactory(EditOfferCell.forTable(new PriceStringConverter(), false));
sell.setCellFactory(EditOfferCell.forTable(new PriceStringConverter(), true));
actSave.disabledProperty().bind(x.wrongProperty().or(y.wrongProperty().or(z.wrongProperty())));
fillItems();
name.setOnAction((v)->x.requestFocus());
@@ -90,7 +104,7 @@ public class VendorEditorController {
}
Dialog dlg = new Dialog(parent, Localization.getString(vendor == null ? "vEditor.title.add" : "vEditor.title.edit"));
dlg.setContent(content);
dlg.getActions().addAll(actSave, Dialog.Actions.CANCEL);
dlg.getActions().addAll(actSave, actCancel);
dlg.setResizable(false);
return dlg.show();
}
@@ -111,6 +125,7 @@ public class VendorEditorController {
y.setValue(0);
z.setValue(0);
items.getItems().forEach(FakeOffer::reset);
items.getSelectionModel().clearSelection();
}
private void fillItems() {
@@ -226,15 +241,22 @@ public class VendorEditorController {
public void updateFromEMDN(){
Station emdnData = World.getEMDN(vendor.getName());
LOG.debug("Update from EMDN");
if (emdnData == null) return;
LOG.debug("Update {} from EMDN", vendor.getName());
if (emdnData == null){
LOG.trace("Not found in EMDN");
return;
}
for (FakeOffer offer : items.getItems()) {
if (offer.item.isMarketItem()){
ItemData data = emdnData.getData(offer.item.getId());
LOG.debug("Update item {} to {}", offer.item.getName(), data);
if (data != null){
offer.setSprice(data.getBuy());
offer.setBprice(data.getSell());
}
} else {
LOG.trace("Is not market item, skip");
}
}
}
@@ -313,6 +335,14 @@ public class VendorEditorController {
return this.item.equals(item);
}
public double getOldSprice() {
return sell != null ? sell.getPrice() : 0;
}
public double getOldBprice() {
return buy != null ? buy.getPrice() : 0;
}
public void setSell(OfferModel sell) {
this.sell = sell;
sprice.set(sell.getPrice());
@@ -324,10 +354,10 @@ public class VendorEditorController {
}
public void reset(){
sprice.setValue(0);
bprice.setValue(0);
this.sell = null;
this.buy = null;
sprice.setValue(0);
bprice.setValue(0);
}
@Override

View File

@@ -23,6 +23,10 @@ public class ItemModel{
public String getId() {return item.getName();}
public boolean isMarketItem(){
return item.getGroup() != null && item.getGroup().isMarket();
}
public void setName(String value) {
LOG.info("Change name of item {} to {}", item, name);
market.updateName(this, value);

View File

@@ -0,0 +1,54 @@
package ru.trader.view.support.cells;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableRow;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
import javafx.util.Callback;
import javafx.util.StringConverter;
import ru.trader.controllers.VendorEditorController;
public class EditOfferCell extends TextFieldCell<VendorEditorController.FakeOffer, Double> {
private final static String CSS_CHANGE = "change";
private final static String CSS_ADD = "add";
private final static String CSS_REMOVE = "remove";
private boolean isSell;
public EditOfferCell(StringConverter<Double> converter, boolean isSell) {
super(converter);
this.isSell = isSell;
}
public static Callback<TableColumn<VendorEditorController.FakeOffer,Double>, TableCell<VendorEditorController.FakeOffer,Double>> forTable(final StringConverter<Double> converter, boolean isSell) {
return list -> new EditOfferCell(converter, isSell);
}
@Override
protected void outItem() {
VendorEditorController.FakeOffer offer = (VendorEditorController.FakeOffer) getTableRow().getItem();
double d = isSell? offer.getSprice() - offer.getOldSprice() : offer.getBprice() - offer.getOldBprice();
getStyleClass().removeAll(CSS_ADD, CSS_CHANGE, CSS_REMOVE);
if (d!=0){
HBox hBox = new HBox();
Text nTxt = new Text(getConverter().toString(isSell ? offer.getSprice() : offer.getBprice()));
Text diff = new Text(String.format(" (%+.0f)", d));
if (isSell){
getStyleClass().add(offer.isNewSell()? CSS_ADD : offer.isRemoveSell() ? CSS_REMOVE : CSS_CHANGE);
} else {
getStyleClass().add(offer.isNewBuy()? CSS_ADD : offer.isRemoveBuy() ? CSS_REMOVE : CSS_CHANGE);
}
hBox.getChildren().add(nTxt);
if (!offer.isRemoveBuy() && !offer.isRemoveSell() && !offer.isNewBuy() && !offer.isNewSell()){
hBox.getChildren().add(diff);
}
setText(null);
setGraphic(hBox);
} else {
setText(getItemText());
setGraphic(null);
}
}
}

View File

@@ -1,6 +1,7 @@
package ru.trader.view.support.cells;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.control.*;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
@@ -56,7 +57,7 @@ public class TextFieldCell<S,T> extends TableCell<S,T> {
public void updateItem(T item, boolean empty) {
LOG.trace("Update edit");
super.updateItem(item, empty);
if (empty) {
if (empty || getTableRow() == null) {
setText(null);
setGraphic(null);
@@ -89,9 +90,9 @@ public class TextFieldCell<S,T> extends TableCell<S,T> {
}
private void createTextField(){
this.textField = new TextField(getItemText());
this.setGraphic(textField);
textField.prefWidthProperty().bind(this.getTableColumn().widthProperty());
textField = new TextField(getItemText());
textField.prefWidthProperty().bind(getTableColumn().widthProperty());
textField.setPadding(Insets.EMPTY);
textField.setOnKeyPressed(t -> {
if (t.getCode() == KeyCode.ENTER) {
if (commit(true)) ViewUtils.editNext(getTableView());
@@ -104,7 +105,7 @@ public class TextFieldCell<S,T> extends TableCell<S,T> {
}
private String getItemText(){
protected String getItemText(){
return converter.toString(getItem());
}
@@ -132,4 +133,7 @@ public class TextFieldCell<S,T> extends TableCell<S,T> {
return textField == null;
}
public StringConverter<T> getConverter() {
return converter;
}
}

View File

@@ -84,3 +84,20 @@ HBox.fields-group hbox-margin{
-fx-padding: 10;
-fx-alignment: center-left;
}
/* EditOfferCell */
#items .change {
-fx-background-color: lightgreen;
}
#items .remove {
-fx-background-color: lightsalmon;
}
#items .remove .text{
-fx-strikethrough: true;
}
#items .add {
-fx-background-color: lightblue;
}

View File

@@ -28,15 +28,15 @@
<Button prefWidth="30" onAction="#add"><graphic><Glyph text="FontAwesome|PLUS"/></graphic></Button>
<Button prefWidth="30" onAction="#updateFromEMDN"><graphic><Glyph text="FontAwesome|REFRESH"/></graphic></Button>
</VBox>
<TableView fx:id="items" prefWidth="375.0" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="2">
<TableView fx:id="items" prefWidth="395.0" editable="true" GridPane.columnIndex="1" GridPane.rowIndex="2">
<columns>
<TableColumn minWidth="200.0" text="%market.item.name" editable="false">
<cellValueFactory><PropertyValueFactory property="name"/></cellValueFactory>
</TableColumn>
<TableColumn fx:id="buy" minWidth="80.0" text="%market.offer.sell">
<TableColumn fx:id="buy" minWidth="90.0" text="%market.offer.sell">
<cellValueFactory><PropertyValueFactory property="bprice"/></cellValueFactory>
</TableColumn>
<TableColumn fx:id="sell" minWidth="80.0" text="%market.offer.buy">
<TableColumn fx:id="sell" minWidth="90.0" text="%market.offer.buy">
<cellValueFactory><PropertyValueFactory property="sprice"/></cellValueFactory>
</TableColumn>
</columns>

View File

@@ -0,0 +1,5 @@
package ru.trader.core;
public enum GROUP_TYPE {
MARKET, SHIP, OUTFIT
}

View File

@@ -0,0 +1,31 @@
package ru.trader.core;
public class Group {
private final String name;
private final GROUP_TYPE type;
public Group(String name, GROUP_TYPE type) {
this.name = name;
this.type = type;
}
public String getName() {
return name;
}
public boolean isMarket(){
return GROUP_TYPE.MARKET.equals(type);
}
public boolean isShip(){
return GROUP_TYPE.SHIP.equals(type);
}
public boolean isOutfit(){
return GROUP_TYPE.OUTFIT.equals(type);
}
public GROUP_TYPE getType() {
return type;
}
}

View File

@@ -6,6 +6,7 @@ import java.util.Objects;
public class Item implements Comparable<Item>{
private String name;
private Group group;
public Item(String name) {
setName(name);
@@ -30,4 +31,12 @@ public class Item implements Comparable<Item>{
if (this == other) return 0;
return name != null ? other.name != null ? name.compareTo(other.name) : -1 : 0;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
}

View File

@@ -20,6 +20,7 @@ public class MarketDocHandler extends DefaultHandler {
protected final static String VENDOR_LIST = "vendors";
protected final static String VENDOR = "vendor";
protected final static String OFFER = "offer";
protected final static String GROUP = "group";
protected final static String ID_ATTR = "id";
protected final static String NAME_ATTR = "name";
@@ -32,6 +33,7 @@ public class MarketDocHandler extends DefaultHandler {
protected Market world;
protected Vendor curVendor;
protected Group curGroup;
protected final HashMap<String,Item> items = new HashMap<>();
@Override
@@ -48,6 +50,8 @@ public class MarketDocHandler extends DefaultHandler {
break;
case OFFER: parseOffer(attributes);
break;
case GROUP: parseGroup(attributes);
break;
}
}
@@ -56,6 +60,8 @@ public class MarketDocHandler extends DefaultHandler {
switch (qName){
case VENDOR: world.add(curVendor);
break;
case GROUP: curGroup = null;
break;
}
}
@@ -90,6 +96,13 @@ public class MarketDocHandler extends DefaultHandler {
onOffer(offerType, item, price);
}
protected void parseGroup(Attributes attributes) throws SAXException {
String name = attributes.getValue(NAME_ATTR);
GROUP_TYPE type = GROUP_TYPE.valueOf(attributes.getValue(TYPE_ATTR));
LOG.debug("parse group {} ({})", name, type);
onGroup(name, type);
}
protected void onOffer(OFFER_TYPE offerType, Item item, double price){
Offer offer = new Offer(offerType, item, price);
curVendor.add(offer);
@@ -104,10 +117,15 @@ public class MarketDocHandler extends DefaultHandler {
protected void onItem(String name, String id) {
Item item = new Item(name);
item.setGroup(curGroup);
world.add(item);
items.put(id, item);
}
protected void onGroup(String name, GROUP_TYPE type) {
curGroup = new Group(name, type);
}
public Market getWorld(){
return world;
}

View File

@@ -2,10 +2,7 @@ package ru.trader.store;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.trader.core.Item;
import ru.trader.core.Market;
import ru.trader.core.Offer;
import ru.trader.core.Vendor;
import ru.trader.core.*;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
@@ -51,9 +48,16 @@ public class MarketStreamWriter {
protected void writeItems() throws XMLStreamException {
out.writeStartElement(MarketDocHandler.ITEM_LIST);
Group group = null;
for (Item entry : market.getItems()) {
if (group!=entry.getGroup()){
if (group != null) out.writeEndElement();
group = entry.getGroup();
if (group != null) writeGroup(group);
}
writeItem(entry, items.get(entry));
}
if (group != null) out.writeEndElement();
out.writeEndElement();
}
@@ -92,6 +96,12 @@ public class MarketStreamWriter {
out.writeAttribute(MarketDocHandler.PRICE_ATTR, String.valueOf(offer.getPrice()));
}
protected void writeGroup(Group group) throws XMLStreamException {
out.writeStartElement(MarketDocHandler.GROUP);
out.writeAttribute(MarketDocHandler.NAME_ATTR, group.getName());
out.writeAttribute(MarketDocHandler.TYPE_ATTR, group.getType().toString());
}
private static Map<Item, String> generateId(Collection<Item> items){
HashMap<Item, String> res = new HashMap<>(items.size());
int index=0;

View File

@@ -18,10 +18,27 @@
<xs:complexType name="itemsType">
<xs:sequence>
<xs:element name="item" type="itemType" maxOccurs="unbounded"/>
<xs:element name="group" type="groupType" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="item" type="itemType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="groupType">
<xs:sequence>
<xs:element name="item" type="itemType" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="type" type="GROUP_TYPE" use="required"/>
</xs:complexType>
<xs:simpleType name="GROUP_TYPE">
<xs:restriction base="xs:string">
<xs:enumeration value="MARKET"/>
<xs:enumeration value="SHIP"/>
<xs:enumeration value="OUTFIT"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="itemType">
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>