Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.chart; 027 028import javafx.animation.FadeTransition; 029import javafx.animation.ParallelTransition; 030import javafx.collections.FXCollections; 031import javafx.collections.ObservableList; 032import javafx.event.ActionEvent; 033import javafx.event.EventHandler; 034import javafx.scene.Node; 035import javafx.scene.layout.StackPane; 036import javafx.util.Duration; 037 038import com.sun.javafx.charts.Legend; 039import com.sun.javafx.charts.Legend.LegendItem; 040 041/** 042 * Chart type that plots symbols for the data points in a series. 043 */ 044public class ScatterChart<X,Y> extends XYChart<X,Y> { 045 046 // -------------- PRIVATE FIELDS ------------------------------------------ 047 048 private Legend legend = new Legend(); 049 050 // -------------- CONSTRUCTORS ---------------------------------------------- 051 052 /** 053 * Construct a new ScatterChart with the given axis and data. 054 * 055 * @param xAxis The x axis to use 056 * @param yAxis The y axis to use 057 */ 058 public ScatterChart(Axis<X> xAxis, Axis<Y> yAxis) { 059 this(xAxis, yAxis, FXCollections.<Series<X, Y>>observableArrayList()); 060 } 061 062 /** 063 * Construct a new ScatterChart with the given axis and data. 064 * 065 * @param xAxis The x axis to use 066 * @param yAxis The y axis to use 067 * @param data The data to use, this is the actual list used so any changes to it will be reflected in the chart 068 */ 069 public ScatterChart(Axis<X> xAxis, Axis<Y> yAxis, ObservableList<Series<X,Y>> data) { 070 super(xAxis,yAxis); 071 setLegend(legend); 072 setData(data); 073 } 074 075 // -------------- METHODS ------------------------------------------------------------------------------------------ 076 077 /** @inheritDoc */ 078 @Override protected void dataItemAdded(Series<X,Y> series, int itemIndex, Data<X,Y> item) { 079 Node symbol = item.getNode(); 080 // check if symbol has already been created 081 if (symbol == null) { 082 symbol = new StackPane(); 083 item.setNode(symbol); 084 } 085 // set symbol styles 086 symbol.getStyleClass().setAll("chart-symbol", "series" + getData().indexOf(series), "data" + itemIndex, 087 series.defaultColorStyleClass); 088 // add and fade in new symbol if animated 089 if (shouldAnimate()) symbol.setOpacity(0); 090 getPlotChildren().add(symbol); 091 if (shouldAnimate()) { 092 FadeTransition ft = new FadeTransition(Duration.millis(500),symbol); 093 ft.setToValue(1); 094 ft.play(); 095 } 096 } 097 098 /** @inheritDoc */ 099 @Override protected void dataItemRemoved(final Data<X,Y> item, final Series<X,Y> series) { 100 final Node symbol = item.getNode(); 101 if (shouldAnimate()) { 102 // fade out old symbol 103 FadeTransition ft = new FadeTransition(Duration.millis(500),symbol); 104 ft.setToValue(0); 105 ft.setOnFinished(new EventHandler<ActionEvent>() { 106 @Override public void handle(ActionEvent actionEvent) { 107 getPlotChildren().remove(symbol); 108 removeDataItemFromDisplay(series, item); 109 } 110 }); 111 ft.play(); 112 } else { 113 getPlotChildren().remove(symbol); 114 removeDataItemFromDisplay(series, item); 115 } 116 } 117 118 /** @inheritDoc */ 119 @Override protected void dataItemChanged(Data<X, Y> item) { 120 } 121 122 /** @inheritDoc */ 123 @Override protected void seriesAdded(Series<X,Y> series, int seriesIndex) { 124 // handle any data already in series 125 for (int j=0; j<series.getData().size(); j++) { 126 dataItemAdded(series,j,series.getData().get(j)); 127 } 128 } 129 130 /** @inheritDoc */ 131 @Override protected void seriesRemoved(final Series<X,Y> series) { 132 // remove all symbol nodes 133 if (shouldAnimate()) { 134 ParallelTransition pt = new ParallelTransition(); 135 pt.setOnFinished(new EventHandler<ActionEvent>() { 136 public void handle(ActionEvent event) { 137 removeSeriesFromDisplay(series); 138 } 139 }); 140 for (final Data<X,Y> d : series.getData()) { 141 final Node symbol = d.getNode(); 142 // fade out old symbol 143 FadeTransition ft = new FadeTransition(Duration.millis(500),symbol); 144 ft.setToValue(0); 145 ft.setOnFinished(new EventHandler<ActionEvent>() { 146 @Override public void handle(ActionEvent actionEvent) { 147 getPlotChildren().remove(symbol); 148 } 149 }); 150 pt.getChildren().add(ft); 151 } 152 pt.play(); 153 } else { 154 for (final Data<X,Y> d : series.getData()) { 155 final Node symbol = d.getNode(); 156 getPlotChildren().remove(symbol); 157 } 158 removeSeriesFromDisplay(series); 159 } 160 } 161 162 /** @inheritDoc */ 163 @Override protected void layoutPlotChildren() { 164 // update symbol positions 165 for (int seriesIndex=0; seriesIndex < getDataSize(); seriesIndex++) { 166 Series<X,Y> series = getData().get(seriesIndex); 167 for (Data<X,Y> item = series.begin; item != null; item = item.next) { 168 double x = getXAxis().getDisplayPosition(item.getCurrentX()); 169 double y = getYAxis().getDisplayPosition(item.getCurrentY()); 170 Node symbol = item.getNode(); 171 if (symbol != null) { 172 final double w = symbol.prefWidth(-1); 173 final double h = symbol.prefHeight(-1); 174 symbol.resizeRelocate(x-(w/2), y-(h/2),w,h); 175 } 176 } 177 } 178 } 179 180 /** 181 * This is called whenever a series is added or removed and the legend needs to be updated 182 */ 183 @Override protected void updateLegend() { 184 legend.getItems().clear(); 185 if (getData() != null) { 186 for (int seriesIndex=0; seriesIndex< getData().size(); seriesIndex++) { 187 Series<X,Y> series = getData().get(seriesIndex); 188 LegendItem legenditem = new LegendItem(series.getName()); 189 if (!series.getData().isEmpty() && series.getData().get(0).getNode() != null) { 190 legenditem.getSymbol().getStyleClass().addAll(series.getData().get(0).getNode().getStyleClass()); 191 } 192 legend.getItems().add(legenditem); 193 } 194 } 195 if (legend.getItems().size() > 0) { 196 if (getLegend() == null) { 197 setLegend(legend); 198 } 199 } else { 200 setLegend(null); 201 } 202 } 203}