1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation. Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package javafx.scene.control.test.chart.apps;
  26 
  27 import java.util.Arrays;
  28 import java.util.Comparator;
  29 import java.util.Iterator;
  30 import java.util.Random;
  31 import javafx.beans.property.DoubleProperty;
  32 import javafx.beans.property.SimpleDoubleProperty;
  33 import javafx.beans.value.ChangeListener;
  34 import javafx.beans.value.ObservableValue;
  35 import javafx.collections.FXCollections;
  36 import javafx.collections.ObservableList;
  37 import javafx.event.ActionEvent;
  38 import javafx.event.Event;
  39 import javafx.event.EventHandler;
  40 import javafx.scene.Scene;
  41 import javafx.scene.chart.AreaChart;
  42 import javafx.scene.chart.NumberAxis;
  43 import javafx.scene.chart.XYChart;
  44 import javafx.scene.chart.XYChart.Series;
  45 import javafx.scene.control.*;
  46 import static javafx.scene.control.test.chart.apps.CommonFunctions.*;
  47 import javafx.scene.control.test.utils.CommonPropertiesScene;
  48 import javafx.scene.control.test.utils.ptables.PropertiesTable;
  49 import javafx.scene.control.test.utils.ptables.TabPaneWithControl;
  50 import javafx.scene.layout.HBox;
  51 import javafx.scene.layout.VBox;
  52 import test.javaclient.shared.InteroperabilityApp;
  53 import test.javaclient.shared.Utils;
  54 
  55 /**
  56  * @author Alexander Kirov
  57  */
  58 public class NewAreaChartApp extends InteroperabilityApp implements ChartIDsInterface {
  59 
  60     public final static String REMOVE_ITEM_POS_TEXT_FIELD_ID = "REMOVE_ITEM_POS_TEXT_FIELD_ID";
  61     public final static String REMOVE_BUTTON_ID = "REMOVE_BUTTON_ID";
  62     public final static String ADD_ITEM_TEXT_FIELD_ID = "ADD_ITEM_TEXT_FIELD_ID";
  63     public final static String ADD_ITEM_POSITION_TEXT_FIELD_ID = "ADD_ITEM_POSITION_TEXT_FIELD_ID";
  64     public final static String ADD_ITEM_BUTTON_ID = "ADD_ITEM_BUTTON_ID";
  65     public final static String REMOVE_AREA_POS_TEXT_FIELD_ID = "REMOVE_AREA_POS_TEXT_FIELD_ID";
  66     public final static String REMOVE_INDEX_TEXT_FIELD_ID = "REMOVE_INDEX_TEXT_FIELD_ID";
  67     public final static String ADD_AREA_POS_TEXT_FIELD_ID = "ADD_AREA_POS_TEXT_FIELD_ID";
  68     public final static String ADD_INDEX_TEXT_FIELD_ID = "ADD_INDEX_TEXT_FIELD_ID";
  69     public final static String ADD_VALUE_TEXT_FIELD_ID = "ADD_VALUE_TEXT_FIELD_ID";
  70 
  71     public static void main(String[] args) {
  72         Utils.launch(NewAreaChartApp.class, args);
  73     }
  74 
  75     @Override
  76     protected Scene getScene() {
  77         Utils.setTitleToStage(stage, "AreaChartTestApp");
  78         return new NewAreaChartApp.AreaChartScene();
  79     }
  80 
  81     class AreaChartScene extends CommonPropertiesScene {
  82 
  83         //AreaChart to be tested.
  84         AreaChart testedAreaChart;
  85         NumberAxis axis1;
  86         NumberAxis axis2;
  87         TabPaneWithControl pane;
  88 
  89         public AreaChartScene() {
  90             super("AreaChart", 1300, 800);
  91         }
  92 
  93         @Override
  94         final protected void prepareScene() {
  95             Utils.addBrowser(this);
  96 
  97             axis1 = new NumberAxis(0, 100, 10);
  98             axis2 = new NumberAxis(0, 100, 10);
  99             testedAreaChart = getNewChart();
 100             testedAreaChart.setId(TESTED_CHART_ID);
 101 
 102             Button hardResetButton = ButtonBuilder.create().id(HARD_RESET_BUTTON_ID).text("Hard reset").build();
 103             hardResetButton.setOnAction(new EventHandler<ActionEvent>() {
 104                 public void handle(ActionEvent t) {
 105                     HBox hb = (HBox) getRoot();
 106                     hb.getChildren().clear();
 107                     prepareMainSceneStructure();
 108                     prepareScene();
 109                 }
 110             });
 111 
 112             Button softResetButton = ButtonBuilder.create().id(SOFT_RESET_BUTTON_ID).text("Soft reset").build();
 113             softResetButton.setOnAction(new EventHandler<ActionEvent>() {
 114                 public void handle(ActionEvent t) {
 115                     //throw new UnsupportedOperationException("Not supported yet.");
 116                 }
 117             });
 118 
 119             HBox resetButtonsHBox = new HBox();
 120             resetButtonsHBox.getChildren().addAll(hardResetButton, softResetButton);
 121 
 122             VBox vb = new VBox(5);
 123             vb.getChildren().addAll(resetButtonsHBox, getAddAreaHBox(), getAddPointToDataDialog(), getRemovePointFromDataDialog(), getRemoveDataDialog());
 124 
 125             pane = getPaneFor(testedAreaChart, CHART_TAB_NAME, axis1, AXIS_1_TAB_NAME, axis2, AXIS_2_TAB_NAME);
 126 
 127             setTestedControlContainerSize(500, 500);
 128             setTestedControl(testedAreaChart);
 129             setPropertiesContent(pane);
 130             setControllersContent(vb);
 131         }
 132 
 133         public HBox getAddPointToDataDialog() {
 134             HBox hb = new HBox();
 135 
 136             Label lb1 = new Label("To area");
 137             final TextField tf1 = TextFieldBuilder.create().text("0").prefWidth(50).id(ADD_AREA_POS_TEXT_FIELD_ID).build();
 138 
 139             Label lb2 = new Label("to index");
 140             final TextField tf2 = TextFieldBuilder.create().text("0").prefWidth(50).id(ADD_INDEX_TEXT_FIELD_ID).build();
 141 
 142             Label lb3 = new Label("value");
 143             final TextField tf3 = TextFieldBuilder.create().text("0").prefWidth(50).id(ADD_VALUE_TEXT_FIELD_ID).build();
 144 
 145             Button bt = ButtonBuilder.create().text("add point!").id(REMOVE_BUTTON_ID).build();
 146             bt.setOnAction(new EventHandler() {
 147                 public void handle(Event t) {
 148                     int area = Integer.parseInt(tf1.getText());
 149                     int point = Integer.parseInt(tf2.getText());
 150                     double value = Double.parseDouble(tf3.getText());
 151 
 152                     XYChart.Data newData = new XYChart.Data();
 153                     newData.setXValue((((Double) ((XYChart.Data) (((Series) testedAreaChart.getData().get(area)).getData().get(point))).getXValue()) + ((Double) ((XYChart.Data) (((Series) testedAreaChart.getData().get(area)).getData().get(point - 1))).getXValue())) / 2);
 154                     newData.setYValue(value);
 155 
 156                     ((Series) testedAreaChart.getData().get(area)).getData().add(point, newData);
 157                 }
 158             });
 159             hb.getChildren().addAll(lb1, tf1, lb2, tf2, lb3, tf3, bt);
 160             return hb;
 161         }
 162 
 163         public HBox getRemovePointFromDataDialog() {
 164             HBox hb = new HBox();
 165 
 166             Label lb1 = new Label("From area");
 167             final TextField tf1 = TextFieldBuilder.create().text("0").prefWidth(50).id(REMOVE_AREA_POS_TEXT_FIELD_ID).build();
 168 
 169             Label lb2 = new Label("From index");
 170             final TextField tf2 = TextFieldBuilder.create().text("0").prefWidth(50).id(REMOVE_INDEX_TEXT_FIELD_ID).build();
 171 
 172             Button bt = ButtonBuilder.create().text("remove point!").id(REMOVE_BUTTON_ID).build();
 173             bt.setOnAction(new EventHandler() {
 174                 public void handle(Event t) {
 175                     int area = Integer.parseInt(tf1.getText());
 176                     int point = Integer.parseInt(tf2.getText());
 177                     ((Series) testedAreaChart.getData().get(area)).getData().remove(point);
 178                 }
 179             });
 180             hb.getChildren().addAll(lb1, tf1, lb2, tf2, bt);
 181             return hb;
 182         }
 183 
 184         public HBox getRemoveDataDialog() {
 185             HBox hb = new HBox();
 186             Label lb = new Label("From index");
 187             final TextField tf = TextFieldBuilder.create().text("0").prefWidth(50).id(REMOVE_AREA_INDEX_TEXTFIELD_ID).build();
 188             Button bt = ButtonBuilder.create().text("remove area!").id(REMOVE_AREA_BUTTON_ID).build();
 189             bt.setOnAction(new EventHandler() {
 190                 public void handle(Event t) {
 191                     int index = Integer.parseInt(tf.getText());
 192                     testedAreaChart.getData().remove(index);
 193                 }
 194             });
 195             hb.getChildren().addAll(lb, tf, bt);
 196             return hb;
 197         }
 198 
 199         public HBox getAddAreaHBox() {
 200             HBox hb = new HBox();
 201             Label lb = new Label("Add series named ");
 202             final TextField tf = TextFieldBuilder.create().prefWidth(50).id(ADDED_SERIES_NAME_TEXTFIELD_ID).build();
 203 
 204             Label minLabel = new Label(" minX ");
 205             final TextField minText = TextFieldBuilder.create().prefWidth(50).id(ADDED_SERIES_MIN_VALUE_TEXTFIELD_ID).build();
 206 
 207             Label maxLabel = new Label(" maxX ");
 208             final TextField maxText = TextFieldBuilder.create().prefWidth(50).id(ADDED_SERIES_MAX_VALUE_TEXTFIELD_ID).build();
 209 
 210             Label amountLabel = new Label(" with ");
 211             final TextField amountText = TextFieldBuilder.create().prefWidth(50).id(ADDED_SERIES_DOTS_COUNT_TEXTFIELD_ID).build();
 212 
 213             Button bt = ButtonBuilder.create().text("add area!").id(ADD_SERIES_COMMAND_BUTTON_ID).build();
 214             bt.setOnAction(new EventHandler() {
 215                 public void handle(Event t) {
 216                     String serieName = tf.getText();
 217                     double min = Double.parseDouble(minText.getText());
 218                     double max = Double.parseDouble(maxText.getText());
 219                     int amount = Integer.parseInt(amountText.getText());
 220 
 221                     ObservableList list = FXCollections.observableArrayList();
 222 
 223                     for (int i = 0; i < amount; i++) {
 224                         XYChart.Data newData = new XYChart.Data();
 225                         newData.setXValue(new Random().nextDouble() * (max - min) + min);
 226                         newData.setYValue(new Random().nextDouble() * (max - min) + min);
 227                         list.add(newData);
 228                     }
 229                     Object[] array = list.toArray();
 230                     Arrays.sort(array, new Comparator() {
 231                         public int compare(Object t, Object t1) {
 232                             return (int) Math.round(((Double) ((XYChart.Data) t).getXValue()) - ((Double) ((XYChart.Data) t1).getXValue()));
 233                         }
 234                     });
 235 
 236                     XYChart.Series serie = new XYChart.Series(serieName, FXCollections.observableArrayList(array));
 237 
 238                     testedAreaChart.getData().add(serie);
 239                     pane.addPropertiesTable(serieName, getTableForProperty(serie, min, max).getVisualRepresentation());
 240                 }
 241             });
 242             hb.getChildren().addAll(lb, tf, minLabel, minText, maxLabel, maxText, amountLabel, amountText, bt);
 243             return hb;
 244         }
 245 
 246         protected PropertiesTable getTableForProperty(XYChart.Series serie, double min, double max) {
 247             PropertiesTable table = new PropertiesTable(serie);
 248 
 249             table.addSimpleListener(serie.chartProperty(), serie);
 250             table.addSimpleListener(serie.nameProperty(), serie);
 251             table.addSimpleListener(serie.dataProperty(), serie);
 252 
 253             for (Iterator it = serie.getData().iterator(); it.hasNext();) {
 254                 final XYChart.Data data = (XYChart.Data) it.next();
 255 
 256                 final DoubleProperty intermediateX = new SimpleDoubleProperty(null, "XValue");
 257                 final DoubleProperty intermediateY = new SimpleDoubleProperty(null, "YValue");
 258 
 259                 data.XValueProperty().addListener(new ChangeListener() {
 260                     public void changed(ObservableValue ov, Object t, Object t1) {
 261                         if (!intermediateX.isBound()) {
 262                             intermediateX.setValue((Double) data.XValueProperty().getValue());
 263                         }
 264                     }
 265                 });
 266 
 267                 data.YValueProperty().addListener(new ChangeListener() {
 268                     public void changed(ObservableValue ov, Object t, Object t1) {
 269                         if (!intermediateY.isBound()) {
 270                             intermediateY.setValue((Double) data.YValueProperty().getValue());
 271                         }
 272                     }
 273                 });
 274 
 275                 intermediateX.addListener(new ChangeListener() {
 276                     public void changed(ObservableValue ov, Object t, Object t1) {
 277                         data.setXValue(t1);
 278                     }
 279                 });
 280 
 281                 intermediateY.addListener(new ChangeListener() {
 282                     public void changed(ObservableValue ov, Object t, Object t1) {
 283                         data.setYValue(t1);
 284                     }
 285                 });
 286 
 287                 table.addDoublePropertyLine(intermediateX, min, max, (Double) data.getXValue(), data);
 288                 table.addDoublePropertyLine(intermediateY, min, max, (Double) data.getYValue(), data);
 289             }
 290 
 291             return table;
 292         }
 293 
 294         public AreaChart getNewChart() {
 295             AreaChart chart = new AreaChart(axis1, axis2);
 296             chart.setTitle("AreaChart");
 297             chart.setStyle("-fx-border-color: darkgray;");
 298             return chart;
 299         }
 300     }
 301 }