Move candlechart classes, fix redraw bug

This commit is contained in:
Manfred Karrer 2016-07-23 22:42:20 +02:00
parent 3d11f8295d
commit bd4f0742fd
11 changed files with 112 additions and 99 deletions

View file

@ -175,7 +175,7 @@ public class BitsquareApp extends Application {
scene.getStylesheets().setAll( scene.getStylesheets().setAll(
"/io/bitsquare/gui/bitsquare.css", "/io/bitsquare/gui/bitsquare.css",
"/io/bitsquare/gui/images.css", "/io/bitsquare/gui/images.css",
"/io/bitsquare/gui/components/candlestick/CandleStickChart.css"); "/io/bitsquare/gui/CandleStickChart.css");
// configure the system tray // configure the system tray
SystemTray.create(primaryStage, shutDownHandler); SystemTray.create(primaryStage, shutDownHandler);

View file

@ -18,10 +18,9 @@
package io.bitsquare.gui.main.markets.trades; package io.bitsquare.gui.main.markets.trades;
import io.bitsquare.common.UserThread; import io.bitsquare.common.UserThread;
import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.candlestick.CandleStickChart; import io.bitsquare.gui.main.markets.trades.candlestick.CandleStickChart;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import io.bitsquare.locale.CryptoCurrency; import io.bitsquare.locale.CryptoCurrency;
import io.bitsquare.locale.FiatCurrency; import io.bitsquare.locale.FiatCurrency;
@ -58,7 +57,6 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
private NumberAxis xAxis, yAxis; private NumberAxis xAxis, yAxis;
XYChart.Series<Number, Number> series; XYChart.Series<Number, Number> series;
private final ListChangeListener<XYChart.Data<Number, Number>> itemsChangeListener; private final ListChangeListener<XYChart.Data<Number, Number>> itemsChangeListener;
private final Navigation navigation;
private final BSFormatter formatter; private final BSFormatter formatter;
private TableView<TradeStatistics> tableView; private TableView<TradeStatistics> tableView;
private ComboBox<TradeCurrency> currencyComboBox; private ComboBox<TradeCurrency> currencyComboBox;
@ -73,9 +71,8 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@Inject @Inject
public TradesChartsView(TradesChartsViewModel model, Navigation navigation, BSFormatter formatter) { public TradesChartsView(TradesChartsViewModel model, BSFormatter formatter) {
super(model); super(model);
this.navigation = navigation;
this.formatter = formatter; this.formatter = formatter;
itemsChangeListener = c -> updateChartData(); itemsChangeListener = c -> updateChartData();
@ -154,6 +151,89 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
} }
private void createChart() {
xAxis = new NumberAxis(0, model.upperBound + 1, 1);
xAxis.setTickUnit(1);
// final double lowerBound = (double) model.getTimeInterval(0, model.tickUnit);
//xAxis.setLowerBound(lowerBound);
//final long minWith = (long) root.getWidth() / 20;
//final double upperBound = (double) minWith;
// xAxis.setUpperBound(upperBound);
xAxis.setMinorTickCount(0);
xAxis.setForceZeroInRange(false);
//xAxis.setAutoRanging(true);
xAxis.setLabel("Date/Time");
xAxis.setTickLabelFormatter(getXAxisStringConverter());
yAxis = new NumberAxis();
yAxis.setForceZeroInRange(false);
yAxis.setAutoRanging(true);
yAxis.setLabel(priceColumnLabel.get());
yAxis.setTickLabelFormatter(getStringConverter());
series = new XYChart.Series<>();
candleStickChart = new CandleStickChart(xAxis, yAxis);
candleStickChart.setData(FXCollections.observableArrayList(series));
candleStickChart.setAnimated(true);
candleStickChart.setId("charts");
candleStickChart.setMinHeight(300);
candleStickChart.setPadding(new Insets(0, 30, 10, 0));
candleStickChart.setToolTipStringConverter(getStringConverter());
}
@NotNull
private StringConverter<Number> getXAxisStringConverter() {
return new StringConverter<Number>() {
@Override
public String toString(Number object) {
// comes as double
long index = new Double((double) object).longValue();
final long now = model.getTickFromTime(new Date().getTime(), model.tickUnit);
final long tick = now - (model.upperBound - index);
final long time = model.getTimeFromTick(tick, model.tickUnit);
if (model.tickUnit.ordinal() <= TradesChartsViewModel.TickUnit.DAY.ordinal())
return index % 7 == 0 ? formatter.formatDate(new Date(time)) : "";
else
return index % 4 == 0 ? formatter.formatTime(new Date(time)) : "";
}
@Override
public Number fromString(String string) {
return null;
}
};
}
private void updateChartData() {
series.getData().clear();
candleStickChart.getData().clear();
series = new XYChart.Series<>();
candleStickChart.setData(FXCollections.observableArrayList(series));
series.getData().addAll(model.getItems());
xAxis.setTickLabelFormatter(getXAxisStringConverter());
// xAxis.setLowerBound((double) model.getTimeInterval(0, model.tickUnit));
//xAxis.setUpperBound((double) model.getTimeInterval((long) root.getWidth() / 20, model.tickUnit));
}
@NotNull
private StringConverter<Number> getStringConverter() {
return new StringConverter<Number>() {
@Override
public String toString(Number object) {
// comes as double
return formatter.formatFiat(Fiat.valueOf(model.getCurrencyCode(), new Double((double) object).longValue()));
}
@Override
public Number fromString(String string) {
return null;
}
};
}
private VBox getTableBox() { private VBox getTableBox() {
tableView = new TableView<>(); tableView = new TableView<>();
@ -296,83 +376,4 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
return vBox; return vBox;
} }
private void createChart() {
xAxis = new NumberAxis(0, model.upperBound + 1, 1);
xAxis.setTickUnit(1);
// final double lowerBound = (double) model.getTimeInterval(0, model.tickUnit);
//xAxis.setLowerBound(lowerBound);
//final long minWith = (long) root.getWidth() / 20;
//final double upperBound = (double) minWith;
// xAxis.setUpperBound(upperBound);
xAxis.setMinorTickCount(0);
xAxis.setForceZeroInRange(false);
//xAxis.setAutoRanging(true);
xAxis.setLabel("Date/Time");
xAxis.setTickLabelFormatter(new StringConverter<Number>() {
@Override
public String toString(Number object) {
// comes as double
long index = new Double((double) object).longValue();
// int pos = model.upperBound - index;
// model.getTickFromTime(new Date().getTime(), model.tickUnit);
//final long time1 = model.getTickFromTime(e.tradeDateAsTime, model.tickUnit);
final long now = model.getTickFromTime(new Date().getTime(), model.tickUnit);
// long index11 = model.upperBound - (now - time);
final long tick = now - (model.upperBound - index);
final long time = model.getTimeFromTick(tick, model.tickUnit);
if (model.tickUnit.ordinal() <= TradesChartsViewModel.TickUnit.DAY.ordinal())
return index % 7 == 0 ? formatter.formatDate(new Date(time)) : "";
else
return index % 4 == 0 ? formatter.formatTime(new Date(time)) : "";
}
@Override
public Number fromString(String string) {
return null;
}
});
yAxis = new NumberAxis();
yAxis.setForceZeroInRange(false);
yAxis.setAutoRanging(true);
yAxis.setLabel(priceColumnLabel.get());
yAxis.setTickLabelFormatter(getStringConverter());
series = new XYChart.Series<>();
candleStickChart = new CandleStickChart(xAxis, yAxis);
candleStickChart.setData(FXCollections.observableArrayList(series));
//candleStickChart.setAnimated(false);
candleStickChart.setId("charts");
candleStickChart.setMinHeight(300);
candleStickChart.setPadding(new Insets(0, 30, 10, 0));
candleStickChart.setToolTipStringConverter(getStringConverter());
}
@NotNull
private StringConverter<Number> getStringConverter() {
return new StringConverter<Number>() {
@Override
public String toString(Number object) {
// comes as double
return formatter.formatFiat(Fiat.valueOf(model.getCurrencyCode(), new Double((double) object).longValue()));
}
@Override
public Number fromString(String string) {
return null;
}
};
}
private void updateChartData() {
series.getData().clear();
series.getData().addAll(model.getItems());
// xAxis.setLowerBound((double) model.getTimeInterval(0, model.tickUnit));
//xAxis.setUpperBound((double) model.getTimeInterval((long) root.getWidth() / 20, model.tickUnit));
}
} }

View file

@ -20,7 +20,8 @@ package io.bitsquare.gui.main.markets.trades;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject; import com.google.inject.Inject;
import io.bitsquare.gui.common.model.ActivatableViewModel; import io.bitsquare.gui.common.model.ActivatableViewModel;
import io.bitsquare.gui.components.candlestick.CandleStickExtraValues; import io.bitsquare.gui.main.markets.trades.candlestick.CandleData;
import io.bitsquare.gui.main.markets.trades.candlestick.CandleStickExtraValues;
import io.bitsquare.locale.CurrencyUtil; import io.bitsquare.locale.CurrencyUtil;
import io.bitsquare.locale.TradeCurrency; import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.p2p.P2PService; import io.bitsquare.p2p.P2PService;
@ -61,7 +62,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
ObservableList<XYChart.Data<Number, Number>> items = FXCollections.observableArrayList(); ObservableList<XYChart.Data<Number, Number>> items = FXCollections.observableArrayList();
private P2PService p2PService; private P2PService p2PService;
final ObservableList<TradeStatistics> tradeStatistics = FXCollections.observableArrayList(); final ObservableList<TradeStatistics> tradeStatistics = FXCollections.observableArrayList();
TickUnit tickUnit = TickUnit.HOUR; TickUnit tickUnit = TickUnit.MINUTE;
int upperBound = 30; int upperBound = 30;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////

View file

@ -29,7 +29,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package io.bitsquare.gui.components.candlestick; package io.bitsquare.gui.main.markets.trades.candlestick;
import javafx.scene.Group; import javafx.scene.Group;
import javafx.scene.control.Tooltip; import javafx.scene.control.Tooltip;

View file

@ -1,4 +1,4 @@
package io.bitsquare.gui.main.markets.trades; package io.bitsquare.gui.main.markets.trades.candlestick;
public class CandleData { public class CandleData {
public final long tick; // Is the time tick in the chosen time interval public final long tick; // Is the time tick in the chosen time interval

View file

@ -29,7 +29,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package io.bitsquare.gui.components.candlestick; package io.bitsquare.gui.main.markets.trades.candlestick;
import javafx.animation.FadeTransition; import javafx.animation.FadeTransition;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
@ -42,6 +42,8 @@ import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path; import javafx.scene.shape.Path;
import javafx.util.Duration; import javafx.util.Duration;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
@ -55,7 +57,9 @@ import java.util.List;
* extra value property using a CandleStickExtraValues object. * extra value property using a CandleStickExtraValues object.
*/ */
public class CandleStickChart extends XYChart<Number, Number> { public class CandleStickChart extends XYChart<Number, Number> {
private static final Logger log = LoggerFactory.getLogger(CandleStickChart.class);
private StringConverter<Number> toolTipStringConverter; private StringConverter<Number> toolTipStringConverter;
private Path seriesPath;
// -------------- CONSTRUCTORS ---------------------------------------------- // -------------- CONSTRUCTORS ----------------------------------------------
@ -160,17 +164,18 @@ public class CandleStickChart extends XYChart<Number, Number> {
@Override @Override
protected void dataItemRemoved(XYChart.Data<Number, Number> item, XYChart.Series<Number, Number> series) { protected void dataItemRemoved(XYChart.Data<Number, Number> item, XYChart.Series<Number, Number> series) {
final Node candle = item.getNode(); seriesPath.getElements().clear();
final Node node = item.getNode();
if (shouldAnimate()) { if (shouldAnimate()) {
// fade out old candle // fade out old candle
FadeTransition ft = new FadeTransition(Duration.millis(500), candle); FadeTransition ft = new FadeTransition(Duration.millis(500), node);
ft.setToValue(0); ft.setToValue(0);
ft.setOnFinished((ActionEvent actionEvent) -> { ft.setOnFinished((ActionEvent actionEvent) -> {
getPlotChildren().remove(candle); getPlotChildren().remove(node);
}); });
ft.play(); ft.play();
} else { } else {
getPlotChildren().remove(candle); getPlotChildren().remove(node);
} }
} }
@ -192,7 +197,7 @@ public class CandleStickChart extends XYChart<Number, Number> {
} }
} }
// create series path // create series path
Path seriesPath = new Path(); seriesPath = new Path();
seriesPath.getStyleClass().setAll("candlestick-average-line", "series" + seriesIndex); seriesPath.getStyleClass().setAll("candlestick-average-line", "series" + seriesIndex);
series.setNode(seriesPath); series.setNode(seriesPath);
getPlotChildren().add(seriesPath); getPlotChildren().add(seriesPath);
@ -215,6 +220,11 @@ public class CandleStickChart extends XYChart<Number, Number> {
getPlotChildren().remove(candle); getPlotChildren().remove(candle);
} }
} }
if (series.getNode() instanceof Path) {
Path seriesPath = (Path) series.getNode();
seriesPath.getElements().clear();
}
} }
/** /**

View file

@ -29,7 +29,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package io.bitsquare.gui.components.candlestick; package io.bitsquare.gui.main.markets.trades.candlestick;
import javafx.application.Application; import javafx.application.Application;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@ -108,7 +108,7 @@ public class CandleStickChartApp extends Application {
@Override @Override
public void start(Stage primaryStage) throws Exception { public void start(Stage primaryStage) throws Exception {
final Scene scene = new Scene(createContent()); final Scene scene = new Scene(createContent());
scene.getStylesheets().add("/io/bitsquare/gui/components/candlestick/CandleStickChart.css"); scene.getStylesheets().add("/io/bitsquare/gui/CandleStickChart.css");
primaryStage.setScene(scene); primaryStage.setScene(scene);
primaryStage.show(); primaryStage.show();

View file

@ -29,7 +29,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package io.bitsquare.gui.components.candlestick; package io.bitsquare.gui.main.markets.trades.candlestick;
/** /**
* Data extra values for storing close, high and low. * Data extra values for storing close, high and low.

View file

@ -29,7 +29,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
package io.bitsquare.gui.components.candlestick; package io.bitsquare.gui.main.markets.trades.candlestick;
import io.bitsquare.gui.util.BSFormatter; import io.bitsquare.gui.util.BSFormatter;
import javafx.scene.control.Label; import javafx.scene.control.Label;

View file

@ -1,5 +1,6 @@
package io.bitsquare.gui.main.markets.trades; package io.bitsquare.gui.main.markets.trades;
import io.bitsquare.gui.main.markets.trades.candlestick.CandleData;
import io.bitsquare.trade.TradeStatistics; import io.bitsquare.trade.TradeStatistics;
import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.Offer;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;