< prev index next >

modules/javafx.controls/src/main/java/javafx/scene/chart/StackedBarChart.java

Print this page




 216 
 217     @Override protected void dataItemRemoved(final Data<X, Y> item, final Series<X, Y> series) {
 218         final Node bar = item.getNode();
 219 
 220         if (bar != null) {
 221             bar.focusTraversableProperty().unbind();
 222         }
 223 
 224         if (shouldAnimate()) {
 225             Timeline t = createDataRemoveTimeline(item, bar, series);
 226             t.setOnFinished(event -> {
 227                 removeDataItemFromDisplay(series, item);
 228             });
 229             t.play();
 230         } else {
 231             processDataRemove(series, item);
 232             removeDataItemFromDisplay(series, item);
 233         }
 234     }
 235 
 236     /** @inheritDoc */
 237     @Override protected void dataItemChanged(Data<X, Y> item) {
 238         double barVal;
 239         double currentVal;
 240         if (orientation == Orientation.VERTICAL) {
 241             barVal = ((Number) item.getYValue()).doubleValue();
 242             currentVal = ((Number) getCurrentDisplayedYValue(item)).doubleValue();
 243         } else {
 244             barVal = ((Number) item.getXValue()).doubleValue();
 245             currentVal = ((Number) getCurrentDisplayedXValue(item)).doubleValue();
 246         }
 247         if (currentVal > 0 && barVal < 0) { // going from positive to negative
 248             // add style class negative
 249             item.getNode().getStyleClass().add("negative");
 250         } else if (currentVal < 0 && barVal > 0) { // going from negative to positive
 251             // remove style class negative
 252             item.getNode().getStyleClass().remove("negative");
 253         }
 254     }
 255 
 256     @Override protected void seriesChanged(ListChangeListener.Change<? extends Series> c) {
 257         // Update style classes for all series lines and symbols
 258         // Note: is there a more efficient way of doing this?
 259         for (int i = 0; i < getDataSize(); i++) {
 260             final Series<X,Y> series = getData().get(i);
 261             for (int j=0; j<series.getData().size(); j++) {
 262                 Data<X,Y> item = series.getData().get(j);
 263                 Node bar = item.getNode();
 264                 bar.getStyleClass().setAll("chart-bar", "series" + i, "data" + j, series.defaultColorStyleClass);
 265             }
 266         }
 267     }
 268 
 269     /** @inheritDoc */
 270     @Override protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
 271         // handle any data already in series
 272         // create entry in the map
 273         Map<String, List<Data<X, Y>>> categoryMap = new HashMap<String, List<Data<X, Y>>>();
 274         for (int j = 0; j < series.getData().size(); j++) {
 275             Data<X, Y> item = series.getData().get(j);
 276             Node bar = createBar(series, seriesIndex, item, j);
 277             String category;
 278             if (orientation == Orientation.VERTICAL) {
 279                 category = (String) item.getXValue();
 280             } else {
 281                 category = (String) item.getYValue();
 282             }
 283             // list of two item positive and negative
 284             List<Data<X, Y>> itemList = categoryMap.get(category) != null ? categoryMap.get(category) : new ArrayList<Data<X, Y>>();
 285             itemList.add(item);
 286             categoryMap.put(category, itemList);
 287             if (shouldAnimate()) {
 288                 animateDataAdd(item, bar);
 289             } else {


 319                     FadeTransition ft = new FadeTransition(Duration.millis(700), bar);
 320                     ft.setFromValue(1);
 321                     ft.setToValue(0);
 322                     ft.setOnFinished(actionEvent -> {
 323                         processDataRemove(series, d);
 324                         bar.setOpacity(1.0);
 325                     });
 326                     pt.getChildren().add(ft);
 327                 }
 328             }
 329             pt.play();
 330         } else {
 331             for (Data<X, Y> d : series.getData()) {
 332                 processDataRemove(series, d);
 333             }
 334             removeSeriesFromDisplay(series);
 335             requestChartLayout();
 336         }
 337     }
 338 
 339     /** @inheritDoc */
 340     @Override protected void updateAxisRange() {
 341         // This override is necessary to update axis range based on cumulative Y value for the
 342         // Y axis instead of the inherited way where the max value in the data range is used.
 343         boolean categoryIsX = categoryAxis == getXAxis();
 344         if (categoryAxis.isAutoRanging()) {
 345             List cData = new ArrayList();
 346             for (Series<X, Y> series : getData()) {
 347                 for (Data<X, Y> data : series.getData()) {
 348                     if (data != null) cData.add(categoryIsX ? data.getXValue() : data.getYValue());
 349                 }
 350             }
 351             categoryAxis.invalidateRange(cData);
 352         }
 353         if (valueAxis.isAutoRanging()) {
 354             List<Number> vData = new ArrayList<>();
 355             for (String category : categoryAxis.getAllDataCategories()) {
 356                 double totalXN = 0;
 357                 double totalXP = 0;
 358                 Iterator<Series<X, Y>> seriesIterator = getDisplayedSeriesIterator();
 359                 while (seriesIterator.hasNext()) {
 360                     Series<X, Y> series = seriesIterator.next();
 361                     for (final Data<X, Y> item : getDataItem(series, category)) {
 362                         if (item != null) {
 363                             boolean isNegative = item.getNode().getStyleClass().contains("negative");
 364                             Number value = (Number) (categoryIsX ? item.getYValue() : item.getXValue());
 365                             if (!isNegative) {
 366                                 totalXP += valueAxis.toNumericValue(value);
 367                             } else {
 368                                 totalXN += valueAxis.toNumericValue(value);
 369                             }
 370                         }
 371                     }
 372                 }
 373                 vData.add(totalXP);
 374                 vData.add(totalXN);
 375             }
 376             valueAxis.invalidateRange(vData);
 377         }
 378     }
 379 
 380     /** @inheritDoc */
 381     @Override protected void layoutPlotChildren() {
 382         double catSpace = categoryAxis.getCategorySpacing();
 383         // calculate bar spacing
 384         final double availableBarSpace = catSpace - getCategoryGap();
 385         final double barWidth = availableBarSpace;
 386         final double barOffset = -((catSpace - getCategoryGap()) / 2);
 387         // update bar positions and sizes
 388         for (String category : categoryAxis.getCategories()) {
 389             double currentPositiveValue = 0;
 390             double currentNegativeValue = 0;
 391             Iterator<Series<X, Y>> seriesIterator = getDisplayedSeriesIterator();
 392             while (seriesIterator.hasNext()) {
 393                 Series<X, Y> series = seriesIterator.next();
 394                 for (final Data<X, Y> item : getDataItem(series, category)) {
 395                     if (item != null) {
 396                         final Node bar = item.getNode();
 397                         final double categoryPos;
 398                         final double valNumber;
 399                         final X xValue = getCurrentDisplayedXValue(item);
 400                         final Y yValue = getCurrentDisplayedYValue(item);




 216 
 217     @Override protected void dataItemRemoved(final Data<X, Y> item, final Series<X, Y> series) {
 218         final Node bar = item.getNode();
 219 
 220         if (bar != null) {
 221             bar.focusTraversableProperty().unbind();
 222         }
 223 
 224         if (shouldAnimate()) {
 225             Timeline t = createDataRemoveTimeline(item, bar, series);
 226             t.setOnFinished(event -> {
 227                 removeDataItemFromDisplay(series, item);
 228             });
 229             t.play();
 230         } else {
 231             processDataRemove(series, item);
 232             removeDataItemFromDisplay(series, item);
 233         }
 234     }
 235 
 236     /** {@inheritDoc} */
 237     @Override protected void dataItemChanged(Data<X, Y> item) {
 238         double barVal;
 239         double currentVal;
 240         if (orientation == Orientation.VERTICAL) {
 241             barVal = ((Number) item.getYValue()).doubleValue();
 242             currentVal = ((Number) getCurrentDisplayedYValue(item)).doubleValue();
 243         } else {
 244             barVal = ((Number) item.getXValue()).doubleValue();
 245             currentVal = ((Number) getCurrentDisplayedXValue(item)).doubleValue();
 246         }
 247         if (currentVal > 0 && barVal < 0) { // going from positive to negative
 248             // add style class negative
 249             item.getNode().getStyleClass().add("negative");
 250         } else if (currentVal < 0 && barVal > 0) { // going from negative to positive
 251             // remove style class negative
 252             item.getNode().getStyleClass().remove("negative");
 253         }
 254     }
 255 
 256     @Override protected void seriesChanged(ListChangeListener.Change<? extends Series> c) {
 257         // Update style classes for all series lines and symbols
 258         // Note: is there a more efficient way of doing this?
 259         for (int i = 0; i < getDataSize(); i++) {
 260             final Series<X,Y> series = getData().get(i);
 261             for (int j=0; j<series.getData().size(); j++) {
 262                 Data<X,Y> item = series.getData().get(j);
 263                 Node bar = item.getNode();
 264                 bar.getStyleClass().setAll("chart-bar", "series" + i, "data" + j, series.defaultColorStyleClass);
 265             }
 266         }
 267     }
 268 
 269     /** {@inheritDoc} */
 270     @Override protected void seriesAdded(Series<X, Y> series, int seriesIndex) {
 271         // handle any data already in series
 272         // create entry in the map
 273         Map<String, List<Data<X, Y>>> categoryMap = new HashMap<String, List<Data<X, Y>>>();
 274         for (int j = 0; j < series.getData().size(); j++) {
 275             Data<X, Y> item = series.getData().get(j);
 276             Node bar = createBar(series, seriesIndex, item, j);
 277             String category;
 278             if (orientation == Orientation.VERTICAL) {
 279                 category = (String) item.getXValue();
 280             } else {
 281                 category = (String) item.getYValue();
 282             }
 283             // list of two item positive and negative
 284             List<Data<X, Y>> itemList = categoryMap.get(category) != null ? categoryMap.get(category) : new ArrayList<Data<X, Y>>();
 285             itemList.add(item);
 286             categoryMap.put(category, itemList);
 287             if (shouldAnimate()) {
 288                 animateDataAdd(item, bar);
 289             } else {


 319                     FadeTransition ft = new FadeTransition(Duration.millis(700), bar);
 320                     ft.setFromValue(1);
 321                     ft.setToValue(0);
 322                     ft.setOnFinished(actionEvent -> {
 323                         processDataRemove(series, d);
 324                         bar.setOpacity(1.0);
 325                     });
 326                     pt.getChildren().add(ft);
 327                 }
 328             }
 329             pt.play();
 330         } else {
 331             for (Data<X, Y> d : series.getData()) {
 332                 processDataRemove(series, d);
 333             }
 334             removeSeriesFromDisplay(series);
 335             requestChartLayout();
 336         }
 337     }
 338 
 339     /** {@inheritDoc} */
 340     @Override protected void updateAxisRange() {
 341         // This override is necessary to update axis range based on cumulative Y value for the
 342         // Y axis instead of the inherited way where the max value in the data range is used.
 343         boolean categoryIsX = categoryAxis == getXAxis();
 344         if (categoryAxis.isAutoRanging()) {
 345             List cData = new ArrayList();
 346             for (Series<X, Y> series : getData()) {
 347                 for (Data<X, Y> data : series.getData()) {
 348                     if (data != null) cData.add(categoryIsX ? data.getXValue() : data.getYValue());
 349                 }
 350             }
 351             categoryAxis.invalidateRange(cData);
 352         }
 353         if (valueAxis.isAutoRanging()) {
 354             List<Number> vData = new ArrayList<>();
 355             for (String category : categoryAxis.getAllDataCategories()) {
 356                 double totalXN = 0;
 357                 double totalXP = 0;
 358                 Iterator<Series<X, Y>> seriesIterator = getDisplayedSeriesIterator();
 359                 while (seriesIterator.hasNext()) {
 360                     Series<X, Y> series = seriesIterator.next();
 361                     for (final Data<X, Y> item : getDataItem(series, category)) {
 362                         if (item != null) {
 363                             boolean isNegative = item.getNode().getStyleClass().contains("negative");
 364                             Number value = (Number) (categoryIsX ? item.getYValue() : item.getXValue());
 365                             if (!isNegative) {
 366                                 totalXP += valueAxis.toNumericValue(value);
 367                             } else {
 368                                 totalXN += valueAxis.toNumericValue(value);
 369                             }
 370                         }
 371                     }
 372                 }
 373                 vData.add(totalXP);
 374                 vData.add(totalXN);
 375             }
 376             valueAxis.invalidateRange(vData);
 377         }
 378     }
 379 
 380     /** {@inheritDoc} */
 381     @Override protected void layoutPlotChildren() {
 382         double catSpace = categoryAxis.getCategorySpacing();
 383         // calculate bar spacing
 384         final double availableBarSpace = catSpace - getCategoryGap();
 385         final double barWidth = availableBarSpace;
 386         final double barOffset = -((catSpace - getCategoryGap()) / 2);
 387         // update bar positions and sizes
 388         for (String category : categoryAxis.getCategories()) {
 389             double currentPositiveValue = 0;
 390             double currentNegativeValue = 0;
 391             Iterator<Series<X, Y>> seriesIterator = getDisplayedSeriesIterator();
 392             while (seriesIterator.hasNext()) {
 393                 Series<X, Y> series = seriesIterator.next();
 394                 for (final Data<X, Y> item : getDataItem(series, category)) {
 395                     if (item != null) {
 396                         final Node bar = item.getNode();
 397                         final double categoryPos;
 398                         final double valNumber;
 399                         final X xValue = getCurrentDisplayedXValue(item);
 400                         final Y yValue = getCurrentDisplayedYValue(item);


< prev index next >