add prototype route tracker
This commit is contained in:
@@ -1,18 +1,24 @@
|
|||||||
package ru.trader.controllers;
|
package ru.trader.controllers;
|
||||||
|
|
||||||
|
import javafx.beans.InvalidationListener;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.ComboBox;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.ListView;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import ru.trader.analysis.CrawlerSpecificator;
|
import ru.trader.analysis.CrawlerSpecificator;
|
||||||
import ru.trader.model.*;
|
import ru.trader.model.*;
|
||||||
|
import ru.trader.view.support.Track;
|
||||||
import ru.trader.view.support.ViewUtils;
|
import ru.trader.view.support.ViewUtils;
|
||||||
import ru.trader.view.support.autocomplete.AutoCompletion;
|
import ru.trader.view.support.autocomplete.AutoCompletion;
|
||||||
import ru.trader.view.support.autocomplete.SystemsProvider;
|
import ru.trader.view.support.autocomplete.SystemsProvider;
|
||||||
|
import ru.trader.view.support.cells.OfferListCell;
|
||||||
|
import ru.trader.view.support.cells.OrderListCell;
|
||||||
|
import ru.trader.view.support.cells.StationListCell;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -20,18 +26,45 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
public class RouteTrackController {
|
public class RouteTrackController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Node editGroup;
|
||||||
|
@FXML
|
||||||
|
private Node infoGroup;
|
||||||
|
@FXML
|
||||||
|
private Node refuelGroup;
|
||||||
|
@FXML
|
||||||
|
private Node ordersGroup;
|
||||||
|
@FXML
|
||||||
|
private Label station;
|
||||||
|
@FXML
|
||||||
|
private Label system;
|
||||||
|
@FXML
|
||||||
|
private Label time;
|
||||||
|
@FXML
|
||||||
|
private Label refuel;
|
||||||
|
@FXML
|
||||||
|
private ListView<OrderModel> buyOrders;
|
||||||
|
@FXML
|
||||||
|
private ListView<OrderModel> sellOrders;
|
||||||
|
@FXML
|
||||||
|
private ListView<MissionModel> addMissionsList;
|
||||||
@FXML
|
@FXML
|
||||||
private ListView<MissionModel> missionsList;
|
private ListView<MissionModel> missionsList;
|
||||||
@FXML
|
@FXML
|
||||||
private MissionsController missionsController;
|
private MissionsController missionsController;
|
||||||
|
@FXML
|
||||||
|
private Pane track;
|
||||||
|
|
||||||
private RouteModel route;
|
private RouteModel route;
|
||||||
private int index;
|
private Track trackNode;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void initialize(){
|
private void initialize(){
|
||||||
MainController.getProfile().routeProperty().addListener(routeListener);
|
MainController.getProfile().routeProperty().addListener(routeListener);
|
||||||
missionsList.setItems(missionsController.getMissions());
|
addMissionsList.setItems(missionsController.getMissions());
|
||||||
|
buyOrders.setCellFactory(new OrderListCell(false));
|
||||||
|
sellOrders.setCellFactory(new OrderListCell(true));
|
||||||
|
editGroup.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRoute(RouteModel route){
|
public void setRoute(RouteModel route){
|
||||||
@@ -39,23 +72,56 @@ public class RouteTrackController {
|
|||||||
this.route.currentEntryProperty().removeListener(currentEntryListener);
|
this.route.currentEntryProperty().removeListener(currentEntryListener);
|
||||||
}
|
}
|
||||||
this.route = route;
|
this.route = route;
|
||||||
|
fillTrack();
|
||||||
setIndex(route.getCurrentEntry());
|
setIndex(route.getCurrentEntry());
|
||||||
this.route.currentEntryProperty().addListener(currentEntryListener);
|
this.route.currentEntryProperty().addListener(currentEntryListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndex(int index){
|
public void setIndex(int index){
|
||||||
this.index = index;
|
trackNode.setActive(index);
|
||||||
missionsController.setStation(route.get(index).getStation());
|
}
|
||||||
|
|
||||||
|
private void fillTrack(){
|
||||||
|
if (trackNode != null) trackNode.activeProperty().removeListener(activeEntryListener);
|
||||||
|
trackNode = new Track(route);
|
||||||
|
track.getChildren().setAll(trackNode.getNode());
|
||||||
|
trackNode.activeProperty().addListener(activeEntryListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update(){
|
||||||
|
int index = trackNode.getActive();
|
||||||
|
if (index == -1) return;
|
||||||
|
RouteEntryModel entry = route.get(index);
|
||||||
|
missionsController.setStation(entry.getStation());
|
||||||
ObservableList<StationModel> stations = FXCollections.observableArrayList(route.getStations(index));
|
ObservableList<StationModel> stations = FXCollections.observableArrayList(route.getStations(index));
|
||||||
missionsController.getBuyerProvider().setPossibleSuggestions(stations);
|
missionsController.getBuyerProvider().setPossibleSuggestions(stations);
|
||||||
missionsController.getReceiverProvider().setPossibleSuggestions(stations);
|
missionsController.getReceiverProvider().setPossibleSuggestions(stations);
|
||||||
List<ItemModel> items = route.getSellOffers(index).stream().map(OfferModel::getItem).collect(Collectors.toList());
|
List<ItemModel> items = route.getSellOffers(index).stream().map(OfferModel::getItem).collect(Collectors.toList());
|
||||||
missionsController.getItem().getItems().setAll(items);
|
missionsController.getItem().getItems().setAll(items);
|
||||||
|
|
||||||
|
station.setText(entry.getStation().getName());
|
||||||
|
system.setText(entry.getStation().getSystem().getName());
|
||||||
|
time.setText(ViewUtils.timeToString(entry.getTime()));
|
||||||
|
refuel.setText(String.valueOf(entry.getRefill()));
|
||||||
|
buyOrders.setItems(entry.orders());
|
||||||
|
sellOrders.setItems(entry.sellOrders());
|
||||||
|
missionsList.setItems(entry.missions());
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void toggleEdit(){
|
||||||
|
if (editGroup.isVisible()){
|
||||||
|
editGroup.setVisible(false);
|
||||||
|
infoGroup.setVisible(true);
|
||||||
|
} else {
|
||||||
|
editGroup.setVisible(true);
|
||||||
|
infoGroup.setVisible(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private void addMissions(){
|
private void addMissions(){
|
||||||
int startIndex = route.isLoop() ? 0 : index;
|
int startIndex = route.isLoop() ? 0 : trackNode.getActive();
|
||||||
route.addAll(startIndex, missionsList.getItems());
|
route.addAll(startIndex, missionsList.getItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,6 +134,7 @@ public class RouteTrackController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final ChangeListener<? super Number> currentEntryListener = (ov, o, n) -> ViewUtils.doFX(() -> setIndex(n.intValue()));
|
private final ChangeListener<? super Number> currentEntryListener = (ov, o, n) -> ViewUtils.doFX(() -> setIndex(n.intValue()));
|
||||||
|
private final InvalidationListener activeEntryListener = ov -> ViewUtils.doFX(this::update);
|
||||||
private final ChangeListener<RouteModel> routeListener = (ov, o, n) -> {
|
private final ChangeListener<RouteModel> routeListener = (ov, o, n) -> {
|
||||||
if (n != null){
|
if (n != null){
|
||||||
ViewUtils.doFX(() -> setRoute(n));
|
ViewUtils.doFX(() -> setRoute(n));
|
||||||
|
|||||||
@@ -79,6 +79,18 @@ public class RouteEntryModel {
|
|||||||
return entry.isTransit();
|
return entry.isTransit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBuy(){
|
||||||
|
return !orders.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSell(){
|
||||||
|
return !sellOrders.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMissionTarget(){
|
||||||
|
return !missions.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
public ObservableList<OrderModel> orders() {
|
public ObservableList<OrderModel> orders() {
|
||||||
return orders;
|
return orders;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,10 @@ public class RouteModel {
|
|||||||
return entries.get(index);
|
return entries.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<RouteEntryModel> getEntries(){
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
public double getDistance() {
|
public double getDistance() {
|
||||||
return _route.getDistance();
|
return _route.getDistance();
|
||||||
}
|
}
|
||||||
|
|||||||
129
client/src/main/java/ru/trader/view/support/Track.java
Normal file
129
client/src/main/java/ru/trader/view/support/Track.java
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package ru.trader.view.support;
|
||||||
|
|
||||||
|
import javafx.beans.property.IntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.input.MouseButton;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
import javafx.scene.text.Text;
|
||||||
|
import org.controlsfx.glyphfont.Glyph;
|
||||||
|
import ru.trader.model.RouteEntryModel;
|
||||||
|
import ru.trader.model.RouteModel;
|
||||||
|
import ru.trader.model.StationModel;
|
||||||
|
import ru.trader.view.support.cells.DistanceCell;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Track {
|
||||||
|
private final static String CSS_ROUTE = "route";
|
||||||
|
private final static String CSS_ICONS = "route-icons";
|
||||||
|
private final static String CSS_TRACK = "route-track";
|
||||||
|
private final static String CSS_TRACK_TEXT = "route-track-text";
|
||||||
|
private final static String CSS_SYSTEM = "route-system";
|
||||||
|
private final static String CSS_ACTIVE_SYSTEM = "route-active";
|
||||||
|
private final static String CSS_TEXT = "route-text";
|
||||||
|
private final static String CSS_SYSTEM_TEXT = "route-system-text";
|
||||||
|
private final static String CSS_STATION_TEXT = "route-station-text";
|
||||||
|
|
||||||
|
private final RouteModel route;
|
||||||
|
private final HBox node = new HBox();
|
||||||
|
private final IntegerProperty active;
|
||||||
|
private final List<Node> entryNodes;
|
||||||
|
|
||||||
|
public Track(RouteModel route) {
|
||||||
|
this.route = route;
|
||||||
|
entryNodes = new ArrayList<>(route.getJumps());
|
||||||
|
active = new SimpleIntegerProperty(-1);
|
||||||
|
node.getStyleClass().add(CSS_ROUTE);
|
||||||
|
build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build(){
|
||||||
|
StationModel prev = null;
|
||||||
|
for (RouteEntryModel entry : route.getEntries()) {
|
||||||
|
if (prev != null){
|
||||||
|
VBox track = new VBox();
|
||||||
|
VBox.setVgrow(track, Priority.ALWAYS);
|
||||||
|
track.getStyleClass().add(CSS_TRACK);
|
||||||
|
|
||||||
|
Text t = new Text(DistanceCell.distanceToString(entry.getStation().getDistance(prev)));
|
||||||
|
t.getStyleClass().add(CSS_TRACK_TEXT);
|
||||||
|
track.getChildren().addAll(t, Glyph.create("FontAwesome|LONG_ARROW_RIGHT"));
|
||||||
|
|
||||||
|
node.getChildren().addAll(track);
|
||||||
|
}
|
||||||
|
HBox entryNode = new HBox();
|
||||||
|
HBox stationNode = new HBox();
|
||||||
|
VBox icons = new VBox();
|
||||||
|
VBox.setVgrow(icons, Priority.ALWAYS);
|
||||||
|
|
||||||
|
stationNode.getStyleClass().add(CSS_SYSTEM);
|
||||||
|
icons.getStyleClass().add(CSS_ICONS);
|
||||||
|
|
||||||
|
stationNode.getChildren().add(buildText(entry.getStation(), entry.isTransit()));
|
||||||
|
|
||||||
|
if (entry.isBuy()){
|
||||||
|
icons.getChildren().add(Glyph.create("FontAwesome|UPLOAD"));
|
||||||
|
}
|
||||||
|
if (entry.getRefill() > 0){
|
||||||
|
icons.getChildren().add(Glyph.create("FontAwesome|REFRESH"));
|
||||||
|
}
|
||||||
|
if (entry.isSell()){
|
||||||
|
icons.getChildren().add(Glyph.create("FontAwesome|DOWNLOAD"));
|
||||||
|
}
|
||||||
|
entryNode.getChildren().addAll(stationNode, icons);
|
||||||
|
node.getChildren().addAll(entryNode);
|
||||||
|
final int curIndex = entryNodes.size();
|
||||||
|
entryNode.setOnMouseClicked(e -> {
|
||||||
|
if (e.getButton() == MouseButton.PRIMARY){
|
||||||
|
setActive(curIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
entryNodes.add(entryNode);
|
||||||
|
prev = entry.getStation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private VBox buildText(StationModel station, boolean transit){
|
||||||
|
Text systemText = new Text(station.getSystem().getName());
|
||||||
|
systemText.getStyleClass().add(CSS_SYSTEM_TEXT);
|
||||||
|
|
||||||
|
VBox text = new VBox(2);
|
||||||
|
VBox.setVgrow(text, Priority.ALWAYS);
|
||||||
|
text.getStyleClass().add(CSS_TEXT);
|
||||||
|
text.getChildren().addAll(systemText);
|
||||||
|
|
||||||
|
if (!transit) {
|
||||||
|
Text stationText = new Text(station.getName());
|
||||||
|
stationText.getStyleClass().add(CSS_STATION_TEXT);
|
||||||
|
Text distanceText = new Text(String.format("%.0f Ls", station.getDistance()));
|
||||||
|
distanceText.getStyleClass().add(CSS_STATION_TEXT);
|
||||||
|
text.getChildren().addAll(stationText, distanceText);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getActive() {
|
||||||
|
return active.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntegerProperty activeProperty() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(int index){
|
||||||
|
if (this.active.get() != -1){
|
||||||
|
entryNodes.get(this.active.get()).getStyleClass().remove(CSS_ACTIVE_SYSTEM);
|
||||||
|
}
|
||||||
|
this.active.setValue(index);
|
||||||
|
entryNodes.get(index).getStyleClass().add(CSS_ACTIVE_SYSTEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node getNode() {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,10 +10,38 @@
|
|||||||
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
<VBox xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
|
||||||
fx:controller="ru.trader.controllers.RouteTrackController"
|
fx:controller="ru.trader.controllers.RouteTrackController"
|
||||||
spacing="4" >
|
spacing="4" >
|
||||||
|
<HBox fx:id="track" minHeight="100"/>
|
||||||
|
<ToggleButton minWidth="30" onAction="#toggleEdit">
|
||||||
|
<graphic><Glyph text="FontAwesome|EDIT"/></graphic>
|
||||||
|
</ToggleButton>
|
||||||
|
<StackPane>
|
||||||
|
<VBox fx:id="editGroup">
|
||||||
<fx:include fx:id="missions" source="missions.fxml"/>
|
<fx:include fx:id="missions" source="missions.fxml"/>
|
||||||
<HBox>
|
<HBox>
|
||||||
<ListView fx:id="missionsList" />
|
<ListView fx:id="addMissionsList" maxHeight="150"/>
|
||||||
<Button prefWidth="30" onAction="#removeMission"><graphic><Glyph text="FontAwesome|MINUS"/></graphic></Button>
|
<Button prefWidth="30" onAction="#removeMission"><graphic><Glyph text="FontAwesome|MINUS"/></graphic></Button>
|
||||||
<Button prefWidth="80" text="Добавить" onAction="#addMissions" />
|
<Button prefWidth="80" text="Добавить" onAction="#addMissions" />
|
||||||
</HBox>
|
</HBox>
|
||||||
|
</VBox>
|
||||||
|
<VBox fx:id="infoGroup">
|
||||||
|
<HBox><Label text="Система:" /><Label fx:id="system" /></HBox>
|
||||||
|
<HBox><Label text="Станция:" /><Label fx:id="station" /></HBox>
|
||||||
|
<HBox><Label text="Время:" /><Label fx:id="time" /></HBox>
|
||||||
|
<HBox fx:id="refuelGroup"><Label text="Заправить:" /><Label fx:id="refuel" /></HBox>
|
||||||
|
<HBox fx:id="ordersGroup" maxHeight="120">
|
||||||
|
<VBox>
|
||||||
|
<Label text="Продать:" />
|
||||||
|
<ListView fx:id="sellOrders"/>
|
||||||
|
</VBox>
|
||||||
|
<VBox>
|
||||||
|
<Label text="Купить:" />
|
||||||
|
<ListView fx:id="buyOrders"/>
|
||||||
|
</VBox>
|
||||||
|
</HBox>
|
||||||
|
<VBox fx:id="missionsGroup" maxHeight="120">
|
||||||
|
<Label text="Сдать миссии:" />
|
||||||
|
<ListView fx:id="missionsList" maxHeight="150"/>
|
||||||
|
</VBox>
|
||||||
|
</VBox>
|
||||||
|
</StackPane>
|
||||||
</VBox>
|
</VBox>
|
||||||
|
|||||||
@@ -55,47 +55,52 @@ HBox.fields-group hbox-margin{
|
|||||||
|
|
||||||
|
|
||||||
/* Path */
|
/* Path */
|
||||||
.path {
|
.route, .path {
|
||||||
-fx-alignment: center-left;
|
-fx-alignment: center-left;
|
||||||
-fx-spacing: 5px;
|
-fx-spacing: 5px;
|
||||||
-fx-fill-height: true;
|
-fx-fill-height: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-system {
|
.route-system, .path-system {
|
||||||
-fx-alignment: center-left;
|
-fx-alignment: center-left;
|
||||||
-fx-text-alignment: left;
|
-fx-text-alignment: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-text {
|
.route-text, .path-text {
|
||||||
-fx-alignment: center;
|
-fx-alignment: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-system-text {
|
.route-system-text, .path-system-text {
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-station-text {
|
.route-station-text, .path-station-text {
|
||||||
-fx-font-size: 8pt;
|
-fx-font-size: 8pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-icons {
|
.route-icons, .path-icons {
|
||||||
-fx-alignment: center;
|
-fx-alignment: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-track {
|
.route-track, .path-track {
|
||||||
-fx-padding: 0 8;
|
-fx-padding: 0 8;
|
||||||
-fx-alignment: center;
|
-fx-alignment: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.path-track .glyph-font {
|
.route-track .glyph-font, .path-track .glyph-font {
|
||||||
-fx-font-family: FontAwesome;
|
-fx-font-family: FontAwesome;
|
||||||
-fx-font-size: 16pt;
|
-fx-font-size: 16pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.path-track-text {
|
.route-track-text, .path-track-text {
|
||||||
-fx-font-size: 7pt;
|
-fx-font-size: 7pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.route-active {
|
||||||
|
-fx-border-style: solid;
|
||||||
|
-fx-background-color: lightskyblue;
|
||||||
|
}
|
||||||
|
|
||||||
.path-pane {
|
.path-pane {
|
||||||
-fx-padding: 10;
|
-fx-padding: 10;
|
||||||
-fx-alignment: center-left;
|
-fx-alignment: center-left;
|
||||||
|
|||||||
Reference in New Issue
Block a user