diff -r 0b33c9c1d41e javafx-ui-charts/src/javafx/scene/chart/AreaChart.java --- a/javafx-ui-charts/src/javafx/scene/chart/AreaChart.java Thu Jan 31 13:56:14 2013 -0800 +++ b/javafx-ui-charts/src/javafx/scene/chart/AreaChart.java Tue Feb 05 23:22:25 2013 +0100 @@ -53,6 +53,13 @@ import com.sun.javafx.charts.Legend; import com.sun.javafx.charts.Legend.LegendItem; +import com.sun.javafx.css.converters.BooleanConverter; +import java.util.Collections; +import javafx.beans.property.BooleanProperty; +import javafx.css.CssMetaData; +import javafx.css.StyleableBooleanProperty; +import javafx.css.StyleableProperty; +import static javafx.scene.chart.LineChart.getClassCssMetaData; /** * AreaChart - Plots the area between the line that connects the data points and @@ -66,6 +73,54 @@ private Map seriesYMultiplierMap = new HashMap(); private Legend legend = new Legend(); + // -------------- PUBLIC PROPERTIES ---------------------------------------- + + /** When true, CSS styleable symbols are created for any data items that don't have a symbol node specified. */ + private BooleanProperty createSymbols = new StyleableBooleanProperty(true) { + @Override protected void invalidated() { + for (int seriesIndex=0; seriesIndex < getData().size(); seriesIndex ++) { + Series series = getData().get(seriesIndex); + for (int itemIndex=0; itemIndex < series.getData().size(); itemIndex ++) { + Data item = series.getData().get(itemIndex); + Node symbol = item.getNode(); + if(get() && symbol == null) { // create any symbols + symbol = createSymbol(series, getData().indexOf(series), item, itemIndex); + if (null != symbol) { + getPlotChildren().add(symbol); + } + } else if (!get() && symbol != null) { // remove symbols + getPlotChildren().remove(symbol); + symbol = null; + item.setNode(null); + } + } + } + requestChartLayout(); + } + + public Object getBean() { + return this; + } + + public String getName() { + return "createSymbols"; + } + + public CssMetaData getCssMetaData() { + return StyleableProperties.CREATE_SYMBOLS; + } + }; + + /** + * Indicates whether symbols for data points will be created or not. + * + * @return true if symbols for data points will be created and false otherwise. + */ + public final boolean getCreateSymbols() { return createSymbols.getValue(); } + public final void setCreateSymbols(boolean value) { createSymbols.setValue(value); } + public final BooleanProperty createSymbolsProperty() { return createSymbols; } + + // -------------- CONSTRUCTORS ---------------------------------------------- /** @@ -156,7 +211,7 @@ int last = series.getData().size() - 2; item.setCurrentX(series.getData().get(last).getXValue()); item.setCurrentY(series.getData().get(last).getYValue()); - } else { + } else if (symbol != null) { // fade in new symbol FadeTransition ft = new FadeTransition(Duration.millis(500),symbol); ft.setToValue(1); @@ -175,8 +230,9 @@ ); } + } else if (symbol != null) { + getPlotChildren().add(symbol); } - getPlotChildren().add(symbol); } @Override protected void dataItemRemoved(final Data item, final Series series) { @@ -314,12 +370,17 @@ for (int j=0; j nodes = new ArrayList(); nodes.add(series.getNode()); - for (Data d: series.getData()) nodes.add(d.getNode()); + if (getCreateSymbols()) { // RT-22124 + // done need to fade the symbols if createSymbols is false + for (Data d: series.getData()) nodes.add(d.getNode()); + } // fade out old and symbols KeyValue[] startValues = new KeyValue[nodes.size()]; KeyValue[] endValues = new KeyValue[nodes.size()]; @@ -401,13 +465,13 @@ private Node createSymbol(Series series, int seriesIndex, final Data item, int itemIndex) { Node symbol = item.getNode(); // check if symbol has already been created - if (symbol == null) { + if (symbol == null && getCreateSymbols()) { symbol = new StackPane(); item.setNode(symbol); } // set symbol styles // Note: not sure if we want to add or check, ie be more careful and efficient here - symbol.getStyleClass().setAll("chart-area-symbol", "series" + seriesIndex, "data" + itemIndex, + if (symbol != null) symbol.getStyleClass().setAll("chart-area-symbol", "series" + seriesIndex, "data" + itemIndex, series.defaultColorStyleClass); return symbol; } @@ -435,5 +499,48 @@ setLegend(null); } } + + // -------------- STYLESHEET HANDLING -------------------------------------- + + private static class StyleableProperties { + private static final CssMetaData,Boolean> CREATE_SYMBOLS = + new CssMetaData,Boolean>("-fx-create-symbols", + BooleanConverter.getInstance(), Boolean.TRUE) { + + @Override + public boolean isSettable(AreaChart node) { + return node.createSymbols == null || !node.createSymbols.isBound(); + } + + @Override + public StyleableProperty getStyleableProperty(AreaChart node) { + return (StyleableProperty)node.createSymbolsProperty(); + } + }; + + private static final List> STYLEABLES; + static { + final List> styleables = + new ArrayList>(XYChart.getClassCssMetaData()); + styleables.add(CREATE_SYMBOLS); + STYLEABLES = Collections.unmodifiableList(styleables); + } + } + + /** + * @return The CssMetaData associated with this class, which may include the + * CssMetaData of its super classes. + */ + public static List> getClassCssMetaData() { + return StyleableProperties.STYLEABLES; + } + + /** + * {@inheritDoc} + */ + @Override + public List> getCssMetaData() { + return getClassCssMetaData(); + } } diff -r 0b33c9c1d41e javafx-ui-charts/src/javafx/scene/chart/StackedAreaChart.java --- a/javafx-ui-charts/src/javafx/scene/chart/StackedAreaChart.java Thu Jan 31 13:56:14 2013 -0800 +++ b/javafx-ui-charts/src/javafx/scene/chart/StackedAreaChart.java Tue Feb 05 23:22:25 2013 +0100 @@ -41,7 +41,11 @@ import javafx.util.Duration; import com.sun.javafx.charts.Legend; import com.sun.javafx.charts.Legend.LegendItem; +import com.sun.javafx.css.converters.BooleanConverter; +import javafx.beans.property.BooleanProperty; import javafx.css.CssMetaData; +import javafx.css.StyleableBooleanProperty; +import javafx.css.StyleableProperty; import javafx.scene.paint.Color; /** @@ -49,13 +53,13 @@ * contribution of each value. (over time e.g.) The areas are stacked so that each * series adjoins but does not overlap the preceding series. This contrasts with * the Area chart where each series overlays the preceding series. - * + * * The cumulative nature of the StackedAreaChart gives an idea of the total Y data * value at any given point along the X axis. - * + * * Since data points across multiple series may not be common, StackedAreaChart * interpolates values along the line joining the data points whenever necessary. - * + * */ public class StackedAreaChart extends XYChart { @@ -64,7 +68,58 @@ /** A multiplier for teh Y values that we store for each series, it is used to animate in a new series */ private Map seriesYMultiplierMap = new HashMap(); private Legend legend = new Legend(); + + // -------------- PUBLIC PROPERTIES ---------------------------------------- + /** + * When true, CSS styleable symbols are created for any data items that + * don't have a symbol node specified. + */ + private BooleanProperty createSymbols = new StyleableBooleanProperty(true) { + @Override + protected void invalidated() { + for (int seriesIndex = 0; seriesIndex < getData().size(); seriesIndex++) { + Series series = getData().get(seriesIndex); + for (int itemIndex = 0; itemIndex < series.getData().size(); itemIndex++) { + Data item = series.getData().get(itemIndex); + Node symbol = item.getNode(); + if (get() && symbol == null) { // create any symbols + symbol = createSymbol(series, getData().indexOf(series), item, itemIndex); + if (null != symbol) { + getPlotChildren().add(symbol); + } + } else if (!get() && symbol != null) { // remove symbols + getPlotChildren().remove(symbol); + symbol = null; + item.setNode(null); + } + } + } + requestChartLayout(); + } + public Object getBean() { + return this; + } + + public String getName() { + return "createSymbols"; + } + + public CssMetaData getCssMetaData() { + return StyleableProperties.CREATE_SYMBOLS; + } + }; + + /** + * Indicates whether symbols for data points will be created or not. + * + * @return true if symbols for data points will be created and false otherwise. + */ + public final boolean getCreateSymbols() { return createSymbols.getValue(); } + public final void setCreateSymbols(boolean value) { createSymbols.setValue(value); } + public final BooleanProperty createSymbolsProperty() { return createSymbols; } + + // -------------- CONSTRUCTORS ---------------------------------------------- /** @@ -92,7 +147,6 @@ // -------------- METHODS ------------------------------------------------------------------------------------------ - private static double doubleValue(Number number) { return doubleValue(number, 0); } private static double doubleValue(Number number, double nullDefault) { return (number == null) ? nullDefault : number.doubleValue(); } @@ -109,10 +163,10 @@ double y1 = getYAxis().toNumericValue(p1.getYValue()); double x3 = getXAxis().toNumericValue(p2.getXValue()); double y3 = getYAxis().toNumericValue(p2.getYValue()); - + double x2 = getXAxis().toNumericValue(item.getXValue()); double y2 = getYAxis().toNumericValue(item.getYValue()); - + // //1. y intercept of the line : y = ((y3-y1)/(x3-x1)) * x2 + (x3y1 - y3x1)/(x3 -x1) double y = ((y3-y1)/(x3-x1)) * x2 + (x3*y1 - y3*x1)/(x3-x1); item.setCurrentY(getYAxis().toRealValue(y)); @@ -131,7 +185,7 @@ int last = series.getData().size() - 2; item.setCurrentX(series.getData().get(last).getXValue()); item.setCurrentY(series.getData().get(last).getYValue()); - } else { + } else if (symbol != null) { // fade in new symbol FadeTransition ft = new FadeTransition(Duration.millis(500),symbol); ft.setToValue(1); @@ -139,19 +193,20 @@ } if (animate) { animate( - new KeyFrame(Duration.ZERO, new KeyValue(item.currentYProperty(), - item.getCurrentY()), - new KeyValue(item.currentXProperty(), - item.getCurrentX())), - new KeyFrame(Duration.millis(800), new KeyValue(item.currentYProperty(), - item.getYValue(), Interpolator.EASE_BOTH), - new KeyValue(item.currentXProperty(), + new KeyFrame(Duration.ZERO, new KeyValue(item.currentYProperty(), + item.getCurrentY()), + new KeyValue(item.currentXProperty(), + item.getCurrentX())), + new KeyFrame(Duration.millis(800), new KeyValue(item.currentYProperty(), + item.getYValue(), Interpolator.EASE_BOTH), + new KeyValue(item.currentXProperty(), item.getXValue(), Interpolator.EASE_BOTH)) ); } - + + } else if (symbol != null) { + getPlotChildren().add(symbol); } - getPlotChildren().add(symbol); } @Override protected void dataItemRemoved(final Data item, final Series series) { @@ -209,17 +264,17 @@ } if (animate) { animate( new KeyFrame(Duration.ZERO, new KeyValue(item.currentYProperty(), - item.getCurrentY()), new KeyValue(item.currentXProperty(), - item.getCurrentX())), - new KeyFrame(Duration.millis(800), new EventHandler() { + item.getCurrentY()), new KeyValue(item.currentXProperty(), + item.getCurrentX())), + new KeyFrame(Duration.millis(800), new EventHandler() { @Override public void handle(ActionEvent actionEvent) { - getPlotChildren().remove(symbol); - removeDataItemFromDisplay(series, item); - } - }, - new KeyValue(item.currentYProperty(), - item.getYValue(), Interpolator.EASE_BOTH), - new KeyValue(item.currentXProperty(), + getPlotChildren().remove(symbol); + removeDataItemFromDisplay(series, item); + } + }, + new KeyValue(item.currentYProperty(), + item.getYValue(), Interpolator.EASE_BOTH), + new KeyValue(item.currentXProperty(), item.getXValue(), Interpolator.EASE_BOTH)) ); } @@ -246,9 +301,9 @@ final Data item = s.getData().get(j); final Node node = item.getNode(); if(node!=null) node.getStyleClass().setAll("chart-area-symbol", "series" + i, "data" + j, s.defaultColorStyleClass); + } } } - } @Override protected void seriesAdded(Series series, int seriesIndex) { // create new paths for series @@ -274,12 +329,12 @@ if (shouldAnimate()) { // animate in new series keyFrames.add(new KeyFrame(Duration.ZERO, - new KeyValue(seriesLine.opacityProperty(), 0), - new KeyValue(fillPath.opacityProperty(), 0), + new KeyValue(seriesLine.opacityProperty(), 0), + new KeyValue(fillPath.opacityProperty(), 0), new KeyValue(seriesYAnimMultiplier, 0) )); keyFrames.add(new KeyFrame(Duration.millis(200), - new KeyValue(seriesLine.opacityProperty(), 1), + new KeyValue(seriesLine.opacityProperty(), 1), new KeyValue(fillPath.opacityProperty(), 1) )); keyFrames.add(new KeyFrame(Duration.millis(500), @@ -289,16 +344,18 @@ for (int j=0; j series) { // remove series Y multiplier @@ -310,30 +367,43 @@ nodes.add(series.getNode()); for (Data d: series.getData()) nodes.add(d.getNode()); // fade out old and symbols - KeyValue[] startValues = new KeyValue[nodes.size()]; - KeyValue[] endValues = new KeyValue[nodes.size()]; - for (int j=0; j < nodes.size(); j++) { - startValues[j] = new KeyValue(nodes.get(j).opacityProperty(),0); - endValues[j] = new KeyValue(nodes.get(j).opacityProperty(),1); - } - Timeline tl = new Timeline(); - tl.getKeyFrames().addAll( - new KeyFrame(Duration.ZERO,startValues), - new KeyFrame(Duration.millis(400), new EventHandler() { - @Override public void handle(ActionEvent actionEvent) { + if (getCreateSymbols()) { + KeyValue[] startValues = new KeyValue[nodes.size()]; + KeyValue[] endValues = new KeyValue[nodes.size()]; + for (int j=0; j < nodes.size(); j++) { + startValues[j] = new KeyValue(nodes.get(j).opacityProperty(),0); + endValues[j] = new KeyValue(nodes.get(j).opacityProperty(),1); + } + Timeline tl = new Timeline(); + tl.getKeyFrames().addAll( + new KeyFrame(Duration.ZERO,startValues), + new KeyFrame(Duration.millis(400), new EventHandler() { + @Override public void handle(ActionEvent actionEvent) { getPlotChildren().removeAll(nodes); removeSeriesFromDisplay(series); } - },endValues) - ); - tl.play(); + },endValues) + ); + tl.play(); + } else { + Timeline tl = new Timeline(); + tl.getKeyFrames().addAll( + new KeyFrame(Duration.millis(400), new EventHandler() { + @Override public void handle(ActionEvent actionEvent) { + getPlotChildren().removeAll(nodes); + removeSeriesFromDisplay(series); + } + }) + ); + tl.play(); + } } else { getPlotChildren().remove(series.getNode()); for (Data d:series.getData()) getPlotChildren().remove(d.getNode()); removeSeriesFromDisplay(series); } } - + /** @inheritDoc */ @Override protected void updateAxisRange() { // This override is necessary to update axis range based on cumulative Y value for the @@ -346,11 +416,11 @@ for(Series series : getData()) { for(Data data: series.getData()) { if(xData != null) xData.add(data.getXValue()); + } } + if(xData != null) xa.invalidateRange(xData); } - if(xData != null) xa.invalidateRange(xData); - } - } + } if (ya.isAutoRanging()) { List yData = new ArrayList(); if(yData != null) { @@ -361,7 +431,7 @@ Series series = seriesIterator.next(); for(Data item : series.getData()) { if(item != null) maxY = Math.max(maxY, ya.toNumericValue(item.getYValue())); - } + } totalY += maxY; } @@ -374,12 +444,12 @@ /** @inheritDoc */ @Override protected void layoutPlotChildren() { - ArrayList currentSeriesData = - new ArrayList(); + ArrayList currentSeriesData = + new ArrayList(); // AggregateData hold the data points of both the current and the previous series. - // The goal is to collect all the data, sort it and iterate. - ArrayList aggregateData = - new ArrayList(); + // The goal is to collect all the data, sort it and iterate. + ArrayList aggregateData = + new ArrayList(); for (int seriesIndex=0; seriesIndex < getDataSize(); seriesIndex++) { // for every series Series series = getData().get(seriesIndex); aggregateData.clear(); @@ -388,7 +458,7 @@ data.partOf = PartOf.PREVIOUS; aggregateData.add(data); } - currentSeriesData.clear(); + currentSeriesData.clear(); // now copy actual data of the current series. for(Data item = series.begin; item != null; item = item.next) { DataPointInfo itemInfo = new DataPointInfo(item, item.getXValue(), @@ -403,7 +473,7 @@ int dataIndex = 0; // Sort data points from prev and current series sortAggregateList(aggregateData); - + boolean firstCurrent = false; boolean lastCurrent = false; int firstCurrentIndex = findNextCurrent(aggregateData, -1); @@ -419,7 +489,7 @@ DataPointInfo dropDownDataPoint = new DataPointInfo(true); Data item = dataInfo.dataItem; if (dataInfo.partOf.equals(PartOf.CURRENT)) { // handle data from current series - int pIndex = findPreviousPrevious(aggregateData, dataIndex); + int pIndex = findPreviousPrevious(aggregateData, dataIndex); int nIndex = findNextPrevious(aggregateData, dataIndex); DataPointInfo prevPoint; DataPointInfo nextPoint; @@ -431,7 +501,7 @@ y = getYAxis().getZeroPosition(); dropDownDataPoint.setValues(item, item.getXValue(), item.getYValue(), x, y, PartOf.CURRENT, true, false); currentSeriesData.add(dropDownDataPoint); - } + } // And add current point. item = dataInfo.dataItem; x = getXAxis().getDisplayPosition(item.getCurrentX()); @@ -457,20 +527,20 @@ pIndex = findPreviousPrevious(aggregateData, pIndex); prevPoint = (DataPointInfo)aggregateData.get(pIndex); // If lastCurrent - add this drop down - } + } if (prevPoint.x.equals(dataInfo.x)) { // simply add x = getXAxis().getDisplayPosition(item.getCurrentX()); y = getYAxis().getDisplayPosition( - getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue())); + getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue())); y += -(getYAxis().getZeroPosition() - prevPoint.displayY); - currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, x, y, PartOf.CURRENT, false, - (firstCurrent) ? false : true); + currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, x, y, PartOf.CURRENT, false, + (firstCurrent) ? false : true); currentSeriesData.add(currentDataPoint); } if (lastCurrent) { - dropDownDataPoint.setValues(ddPoint.dataItem, ddPoint.x, ddPoint.y, - ddPoint.displayX, ddPoint.displayY, PartOf.CURRENT, true, false); - currentSeriesData.add(dropDownDataPoint); + dropDownDataPoint.setValues(ddPoint.dataItem, ddPoint.x, ddPoint.y, + ddPoint.displayX, ddPoint.displayY, PartOf.CURRENT, true, false); + currentSeriesData.add(dropDownDataPoint); } } else { // interpolate @@ -478,33 +548,33 @@ prevPoint = (pIndex == -1) ? null : (DataPointInfo)aggregateData.get(pIndex); x = getXAxis().getDisplayPosition(item.getCurrentX()); y = getYAxis().getDisplayPosition( - getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue())); + getYAxis().toRealValue(getYAxis().toNumericValue(item.getCurrentY()) * seriesYAnimMultiplier.getValue())); if (prevPoint != null && nextPoint != null) { - double displayY = interpolate(prevPoint.displayX, + double displayY = interpolate(prevPoint.displayX, prevPoint.displayY, nextPoint.displayX, nextPoint.displayY, x); y+= -(getYAxis().getZeroPosition() - displayY); - double dataY = interpolate(getXAxis().toNumericValue(prevPoint.x), - getYAxis().toNumericValue(prevPoint.y), - getXAxis().toNumericValue(nextPoint.x), - getYAxis().toNumericValue(nextPoint.y), - getXAxis().toNumericValue(dataInfo.x)); - if (firstCurrent) { - // now create the drop down point - item = new Data(dataInfo.x, dataY); - dropDownDataPoint.setValues(item, dataInfo.x, getYAxis().toRealValue(dataY), x, displayY, PartOf.CURRENT, true, false); - currentSeriesData.add(dropDownDataPoint); - } - // Add the current point - currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, x, y, PartOf.CURRENT, false, - (firstCurrent) ? false : true); - currentSeriesData.add(currentDataPoint); - if (dataIndex == lastCurrentIndex) { - // add drop down point - item = new Data(dataInfo.x, dataY); - dropDownDataPoint.setValues(item, dataInfo.x, getYAxis().toRealValue(dataY), x, displayY, PartOf.CURRENT, true, false); - currentSeriesData.add(dropDownDataPoint); - } - // Note: add drop down if last current + double dataY = interpolate(getXAxis().toNumericValue(prevPoint.x), + getYAxis().toNumericValue(prevPoint.y), + getXAxis().toNumericValue(nextPoint.x), + getYAxis().toNumericValue(nextPoint.y), + getXAxis().toNumericValue(dataInfo.x)); + if (firstCurrent) { + // now create the drop down point + item = new Data(dataInfo.x, dataY); + dropDownDataPoint.setValues(item, dataInfo.x, getYAxis().toRealValue(dataY), x, displayY, PartOf.CURRENT, true, false); + currentSeriesData.add(dropDownDataPoint); + } + // Add the current point + currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, x, y, PartOf.CURRENT, false, + (firstCurrent) ? false : true); + currentSeriesData.add(currentDataPoint); + if (dataIndex == lastCurrentIndex) { + // add drop down point + item = new Data(dataInfo.x, dataY); + dropDownDataPoint.setValues(item, dataInfo.x, getYAxis().toRealValue(dataY), x, displayY, PartOf.CURRENT, true, false); + currentSeriesData.add(dropDownDataPoint); + } + // Note: add drop down if last current } else { // we do not need to take care of this as it is @@ -512,9 +582,9 @@ } } } - + } else { // handle data from Previous series. - int pIndex = findPreviousCurrent(aggregateData, dataIndex); + int pIndex = findPreviousCurrent(aggregateData, dataIndex); int nIndex = findNextCurrent(aggregateData, dataIndex); DataPointInfo prevPoint; DataPointInfo nextPoint; @@ -522,14 +592,14 @@ if (getXAxis().toNumericValue(dataInfo.x) <= getXAxis().toNumericValue(((DataPointInfo)aggregateData.get(firstCurrentIndex)).x) || getXAxis().toNumericValue(dataInfo.x) > getXAxis().toNumericValue(((DataPointInfo)aggregateData.get(lastCurrentIndex)).x)) { - currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, dataInfo.displayX, dataInfo.displayY, + currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, dataInfo.displayX, dataInfo.displayY, PartOf.CURRENT, true, false); currentDataPoint.dropDown = true; currentSeriesData.add(currentDataPoint); } } else { if (pIndex == -1 || nIndex == -1) { - currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, dataInfo.displayX, dataInfo.displayY, + currentDataPoint.setValues(item, dataInfo.x, dataInfo.y, dataInfo.displayX, dataInfo.displayY, PartOf.CURRENT, true, false); currentSeriesData.add(currentDataPoint); } else { @@ -540,13 +610,13 @@ // interpolate on the current series. prevPoint = (DataPointInfo)aggregateData.get(pIndex); x = getXAxis().getDisplayPosition(item.getCurrentX()); - double dataY = interpolate(getXAxis().toNumericValue(prevPoint.x), - getYAxis().toNumericValue(prevPoint.y), - getXAxis().toNumericValue(nextPoint.x), - getYAxis().toNumericValue(nextPoint.y), - getXAxis().toNumericValue(dataInfo.x)); + double dataY = interpolate(getXAxis().toNumericValue(prevPoint.x), + getYAxis().toNumericValue(prevPoint.y), + getXAxis().toNumericValue(nextPoint.x), + getYAxis().toNumericValue(nextPoint.y), + getXAxis().toNumericValue(dataInfo.x)); y = getYAxis().getDisplayPosition( - getYAxis().toRealValue(dataY * seriesYAnimMultiplier.getValue())); + getYAxis().toRealValue(dataY * seriesYAnimMultiplier.getValue())); y+= -(getYAxis().getZeroPosition() - dataInfo.displayY); currentDataPoint.setValues(new Data(dataInfo.x, dataY), dataInfo.x, getYAxis().toRealValue(0), x, y, PartOf.CURRENT, true, true); currentSeriesData.add(currentDataPoint); @@ -558,7 +628,7 @@ if (firstCurrent) firstCurrent = false; if (lastCurrent) lastCurrent = false; } // end of inner for loop - + // Draw the SeriesLine and Series fill seriesLine.getElements().add(new MoveTo(currentSeriesData.get(0).displayX, currentSeriesData.get(0).displayY)); fillPath.getElements().add(new MoveTo(currentSeriesData.get(0).displayX, currentSeriesData.get(0).displayY)); @@ -570,7 +640,7 @@ } fillPath.getElements().add(new LineTo(point.displayX, point.displayY)); // draw symbols only for actual data points and skip for interpolated points. - if (!point.skipSymbol) { + if (!point.skipSymbol) { Node symbol = point.dataItem.getNode(); if (symbol != null) { final double w = symbol.prefWidth(-1); @@ -586,31 +656,30 @@ } } fillPath.getElements().add(new ClosePath()); - + } // end of out for loop - } - - //-------------------- helper methods to retrieve data points from the previous - // or current data series. - private int findNextCurrent(ArrayList points, int index) { + } + + //-------------------- helper methods to retrieve data points from the previous + // or current data series. + private int findNextCurrent(ArrayList points, int index) { for(int i = index+1; i < points.size(); i++) { if (points.get(i).partOf.equals(PartOf.CURRENT)) { return i; } } return -1; - } - - private int findPreviousCurrent(ArrayList points, int index) { + } + + private int findPreviousCurrent(ArrayList points, int index) { for(int i = index-1; i >= 0; i--) { if (points.get(i).partOf.equals(PartOf.CURRENT)) { return i; } } return -1; - } - - + } + private int findPreviousPrevious(ArrayList points, int index) { for(int i = index-1; i >= 0; i--) { if (points.get(i).partOf.equals(PartOf.PREVIOUS)) { @@ -627,9 +696,9 @@ } return -1; } - + - private void sortAggregateList(ArrayList aggregateList) { + private void sortAggregateList(ArrayList aggregateList) { Collections.sort(aggregateList, new Comparator(){ public int compare(Object o1, Object o2) { Data d1 = ((DataPointInfo)o1).dataItem; @@ -639,23 +708,23 @@ return (val1 < val2 ? -1 : ( val1 == val2) ? 0 : 1); } }); - } - + } + private double interpolate(double lowX, double lowY, double highX, double highY, double x) { - // using y = mx+c find the y for the given x. + // using y = mx+c find the y for the given x. return (((highY - lowY)/(highX - lowX))*(x - lowX))+lowY; } private Node createSymbol(Series series, int seriesIndex, final Data item, int itemIndex) { Node symbol = item.getNode(); // check if symbol has already been created - if (symbol == null) { + if (symbol == null && getCreateSymbols()) { symbol = new StackPane(); item.setNode(symbol); } // set symbol styles // Note not sure if we want to add or check, ie be more careful and efficient here - symbol.getStyleClass().setAll("chart-area-symbol", "series" + seriesIndex, "data" + itemIndex, + if (symbol != null) symbol.getStyleClass().setAll("chart-area-symbol", "series" + seriesIndex, "data" + itemIndex, series.defaultColorStyleClass); return symbol; } @@ -690,7 +759,7 @@ */ final static class DataPointInfo { X x; - Y y; + Y y; double displayX; double displayY; Data dataItem; @@ -698,7 +767,7 @@ boolean skipSymbol = false; // interpolated point - skip drawing symbol boolean lineTo = false; // should there be a lineTo to this point on SeriesLine. boolean dropDown = false; // Is this a drop down point ( non data point). - + //----- Constructors -------------------- DataPointInfo() {} @@ -708,13 +777,13 @@ this.y = y; this.partOf = partOf; } - + DataPointInfo(boolean dropDown) { this.dropDown = dropDown; } - + void setValues(Data item, X x, Y y, double dx, double dy, - PartOf partOf, boolean skipSymbol, boolean lineTo) { + PartOf partOf, boolean skipSymbol, boolean lineTo) { this.dataItem = item; this.x = x; this.y = y; @@ -724,18 +793,18 @@ this.skipSymbol = skipSymbol; this.lineTo = lineTo; } - + public final X getX() { return x; } - + public final Y getY() { return y; } } // To indicate if the data point belongs to the current or the previous series. - enum PartOf { + enum PartOf { CURRENT, PREVIOUS } @@ -743,13 +812,27 @@ // -------------- STYLESHEET HANDLING -------------------------------------- private static class StyleableProperties { + + private static final CssMetaData, Boolean> CREATE_SYMBOLS = + new CssMetaData, Boolean>("-fx-create-symbols", + BooleanConverter.getInstance(), Boolean.TRUE) { + @Override + public boolean isSettable(StackedAreaChart node) { + return node.createSymbols == null || !node.createSymbols.isBound(); + } + @Override + public StyleableProperty getStyleableProperty(StackedAreaChart node) { + return (StyleableProperty) node.createSymbolsProperty(); + } + }; + private static final List> STYLEABLES; - + static { final List> styleables = - new ArrayList>(XYChart.getClassCssMetaData()); - + new ArrayList>(XYChart.getClassCssMetaData()); + styleables.add(CREATE_SYMBOLS); STYLEABLES = Collections.unmodifiableList(styleables); } @@ -759,9 +842,10 @@ * @return The CssMetaData associated with this class, which may include the * CssMetaData of its super classes. */ - public static List> getClassCssMetaData() { - return StyleableProperties.STYLEABLES; - } + public static List> getClassCssMetaData() { + return StyleableProperties.STYLEABLES; + } + /** * {@inheritDoc} */ @@ -769,5 +853,4 @@ public List> getCssMetaData() { return getClassCssMetaData(); } - }