changeset 6939:3c4fb09288b6

RT-36720 [Charts] LineChart connects non-successive data points Reviewed by: jgiles
author Martin Sladecek <martin.sladecek@oracle.com>
date Wed, 30 Apr 2014 08:21:14 +0200
parents 4b558607b25b
children b524bb50da08
files modules/controls/src/main/java/javafx/scene/chart/AreaChart.java modules/controls/src/main/java/javafx/scene/chart/BarChart.java modules/controls/src/main/java/javafx/scene/chart/BubbleChart.java modules/controls/src/main/java/javafx/scene/chart/CategoryAxis.java modules/controls/src/main/java/javafx/scene/chart/LineChart.java modules/controls/src/main/java/javafx/scene/chart/ScatterChart.java
diffstat 6 files changed, 56 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/modules/controls/src/main/java/javafx/scene/chart/AreaChart.java	Wed Apr 30 08:19:53 2014 +0200
+++ b/modules/controls/src/main/java/javafx/scene/chart/AreaChart.java	Wed Apr 30 08:21:14 2014 +0200
@@ -48,6 +48,7 @@
 import javafx.scene.shape.LineTo;
 import javafx.scene.shape.MoveTo;
 import javafx.scene.shape.Path;
+import javafx.scene.shape.PathElement;
 import javafx.scene.shape.StrokeLineJoin;
 import javafx.util.Duration;
 
@@ -452,27 +453,26 @@
 
     /** @inheritDoc */
     @Override protected void layoutPlotChildren() {
+        List<LineTo> constructedPath = new ArrayList<>(getDataSize());
         for (int seriesIndex=0; seriesIndex < getDataSize(); seriesIndex++) {
             Series<X, Y> series = getData().get(seriesIndex);
             DoubleProperty seriesYAnimMultiplier = seriesYMultiplierMap.get(series);
-            boolean isFirst = true;
             double lastX = 0;
-            Path seriesLine = (Path)((Group)series.getNode()).getChildren().get(1);
-            Path fillPath = (Path)((Group)series.getNode()).getChildren().get(0);
-            seriesLine.getElements().clear();
-            fillPath.getElements().clear();
+            final ObservableList<Node> children = ((Group) series.getNode()).getChildren();
+            ObservableList<PathElement> seriesLine = ((Path) children.get(1)).getElements();
+            ObservableList<PathElement> fillPath = ((Path) children.get(0)).getElements();
+            seriesLine.clear();
+            fillPath.clear();
+            constructedPath.clear();
             for (Data<X, Y> item = series.begin; item != null; item = item.next) {
-                double x = lastX = getXAxis().getDisplayPosition(item.getCurrentX());
+                double x = getXAxis().getDisplayPosition(item.getCurrentX());
                 double y = getYAxis().getDisplayPosition(
                         getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue()));
-                if (isFirst) {
-                    isFirst = false;
-                    fillPath.getElements().add(new MoveTo(x, getYAxis().getHeight()));
-                    seriesLine.getElements().add(new MoveTo(x, y));
-                } else {
-                    seriesLine.getElements().add(new LineTo(x, y));
+                constructedPath.add(new LineTo(x, y));
+                if (Double.isNaN(x) || Double.isNaN(y)) {
+                    continue;
                 }
-                fillPath.getElements().add(new LineTo(x, y));
+                lastX = x;
                 Node symbol = item.getNode();
                 if (symbol != null) {
                     final double w = symbol.prefWidth(-1);
@@ -480,12 +480,19 @@
                     symbol.resizeRelocate(x-(w/2), y-(h/2),w,h);
                 }
             }
-            if (fillPath.getElements().size() >= 1) {
-                fillPath.getElements().add(new LineTo(lastX, getYAxis().getHeight()));
-            } else {
-                fillPath.getElements().add(new MoveTo(lastX, getYAxis().getHeight()));
+
+            if (!constructedPath.isEmpty()) {
+                Collections.sort(constructedPath, (e1, e2) -> Double.compare(e1.getX(), e2.getX()));
+                LineTo first = constructedPath.get(0);
+
+                seriesLine.add(new MoveTo(first.getX(), first.getY()));
+                fillPath.add(new MoveTo(first.getX(), getYAxis().getHeight()));
+
+                seriesLine.addAll(constructedPath);
+                fillPath.addAll(constructedPath);
+                fillPath.add(new LineTo(lastX, getYAxis().getHeight()));
+                fillPath.add(new ClosePath());
             }
-            fillPath.getElements().add(new ClosePath());
         }
     }
 
--- a/modules/controls/src/main/java/javafx/scene/chart/BarChart.java	Wed Apr 30 08:19:53 2014 +0200
+++ b/modules/controls/src/main/java/javafx/scene/chart/BarChart.java	Wed Apr 30 08:21:14 2014 +0200
@@ -356,6 +356,9 @@
                         categoryPos = getYAxis().getDisplayPosition(item.getCurrentY());
                         valPos = getXAxis().getDisplayPosition(item.getCurrentX());
                     }
+                    if (Double.isNaN(categoryPos) || Double.isNaN(valPos)) {
+                        continue;
+                    }
                     final double bottom = Math.min(valPos,zeroPos);
                     final double top = Math.max(valPos,zeroPos);
                     bottomPos = bottom;
--- a/modules/controls/src/main/java/javafx/scene/chart/BubbleChart.java	Wed Apr 30 08:19:53 2014 +0200
+++ b/modules/controls/src/main/java/javafx/scene/chart/BubbleChart.java	Wed Apr 30 08:21:14 2014 +0200
@@ -107,6 +107,9 @@
                 Data<X,Y> item = iter.next();
                 double x = getXAxis().getDisplayPosition(item.getCurrentX());
                 double y = getYAxis().getDisplayPosition(item.getCurrentY());
+                if (Double.isNaN(x) || Double.isNaN(y)) {
+                    continue;
+                }
                 Node bubble = item.getNode();
                 Ellipse ellipse;
                 if (bubble != null) {
--- a/modules/controls/src/main/java/javafx/scene/chart/CategoryAxis.java	Wed Apr 30 08:19:53 2014 +0200
+++ b/modules/controls/src/main/java/javafx/scene/chart/CategoryAxis.java	Wed Apr 30 08:21:14 2014 +0200
@@ -458,10 +458,14 @@
      */
     @Override public double getDisplayPosition(String value) {
         // find index of value
+        final ObservableList<String> cat = getCategories();
+        if (!cat.contains(value)) {
+            return Double.NaN;
+        }
         if (getEffectiveSide().isHorizontal()) {
-            return firstCategoryPos.get() + getCategories().indexOf("" + value) * categorySpacing.get();
+            return firstCategoryPos.get() + cat.indexOf(value) * categorySpacing.get();
         } else {
-            return firstCategoryPos.get() + getCategories().indexOf("" + value) * categorySpacing.get() * -1;
+            return firstCategoryPos.get() + cat.indexOf(value) * categorySpacing.get() * -1;
         }
     }
 
--- a/modules/controls/src/main/java/javafx/scene/chart/LineChart.java	Wed Apr 30 08:19:53 2014 +0200
+++ b/modules/controls/src/main/java/javafx/scene/chart/LineChart.java	Wed Apr 30 08:21:14 2014 +0200
@@ -48,6 +48,7 @@
 import javafx.scene.shape.LineTo;
 import javafx.scene.shape.MoveTo;
 import javafx.scene.shape.Path;
+import javafx.scene.shape.PathElement;
 import javafx.scene.shape.StrokeLineJoin;
 import javafx.util.Duration;
 
@@ -439,23 +440,23 @@
 
     /** @inheritDoc */
     @Override protected void layoutPlotChildren() {
+        List<LineTo> constructedPath = new ArrayList<>(getDataSize());
         for (int seriesIndex=0; seriesIndex < getDataSize(); seriesIndex++) {
             Series<X,Y> series = getData().get(seriesIndex);
             final DoubleProperty seriesYAnimMultiplier = seriesYMultiplierMap.get(series);
-            boolean isFirst = true;
             if(series.getNode() instanceof  Path) {
-                Path seriesLine = (Path)series.getNode();
-                seriesLine.getElements().clear();
+                final ObservableList<PathElement> seriesLine = ((Path)series.getNode()).getElements();
+                seriesLine.clear();
+                constructedPath.clear();
                 for (Data<X,Y> item = series.begin; item != null; item = item.next) {
                     double x = getXAxis().getDisplayPosition(item.getCurrentX());
                     double y = getYAxis().getDisplayPosition(
                             getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue()));
-                    if (isFirst) {
-                        isFirst = false;
-                        seriesLine.getElements().add(new MoveTo(x, y));
-                    } else {
-                        seriesLine.getElements().add(new LineTo(x, y));
+                    if (Double.isNaN(x) || Double.isNaN(y)) {
+                        continue;
                     }
+                    constructedPath.add(new LineTo(x, y));
+
                     Node symbol = item.getNode();
                     if (symbol != null) {
                         final double w = symbol.prefWidth(-1);
@@ -463,6 +464,13 @@
                         symbol.resizeRelocate(x-(w/2), y-(h/2),w,h);
                     }
                 }
+                Collections.sort(constructedPath, (e1, e2) -> Double.compare(e1.getX(), e2.getX()));
+
+                if (!constructedPath.isEmpty()) {
+                    LineTo first = constructedPath.get(0);
+                    seriesLine.add(new MoveTo(first.getX(), first.getY()));
+                    seriesLine.addAll(constructedPath);
+                }
             }
         }
     }
--- a/modules/controls/src/main/java/javafx/scene/chart/ScatterChart.java	Wed Apr 30 08:19:53 2014 +0200
+++ b/modules/controls/src/main/java/javafx/scene/chart/ScatterChart.java	Wed Apr 30 08:21:14 2014 +0200
@@ -165,6 +165,9 @@
             for (Data<X,Y> item = series.begin; item != null; item = item.next) {
                 double x = getXAxis().getDisplayPosition(item.getCurrentX());
                 double y = getYAxis().getDisplayPosition(item.getCurrentY());
+                if (Double.isNaN(x) || Double.isNaN(y)) {
+                    continue;
+                }
                 Node symbol = item.getNode();
                 if (symbol != null) {
                     final double w = symbol.prefWidth(-1);