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.LineChart;
  42 import javafx.scene.chart.NumberAxis;
  43 import javafx.scene.chart.XYChart;
  44 import javafx.scene.control.*;
  45 import static javafx.scene.control.test.chart.apps.CommonFunctions.*;
  46 import javafx.scene.control.test.utils.CommonPropertiesScene;
  47 import javafx.scene.control.test.utils.ptables.PropertiesTable;
  48 import javafx.scene.control.test.utils.ptables.TabPaneWithControl;
  49 import javafx.scene.layout.HBox;
  50 import javafx.scene.layout.VBox;
  51 import test.javaclient.shared.InteroperabilityApp;
  52 import test.javaclient.shared.Utils;
  53 
  54 /**
  55  * @author Alexander Kirov
  56  */
  57 public class NewLineChartApp extends InteroperabilityApp implements ChartIDsInterface {
  58 
  59     public final static String REMOVE_ITEM_POS_TEXT_FIELD_ID = "REMOVE_ITEM_POS_TEXT_FIELD_ID";
  60     public final static String REMOVE_BUTTON_ID = "REMOVE_BUTTON_ID";
  61     public final static String ADD_LINE_TEXT_FIELD_ID = "ADD_LINE_TEXT_FIELD_ID";
  62     public final static String ADD_LINE_AT_POSITION_TEXT_FIELD_ID = "ADD_ITEM_POSITION_TEXT_FIELD_ID";
  63     public final static String ADD_LINE_BUTTON_ID = "ADD_ITEM_BUTTON_ID";
  64     public final static String REMOVE_LINE_FROM_POS_TEXT_FIELD_ID = "REMOVE_AREA_POS_TEXT_FIELD_ID";
  65     public final static String REMOVE_INDEX_TEXT_FIELD_ID = "REMOVE_INDEX_TEXT_FIELD_ID";
  66     public final static String ADD_LINE_POS_TEXT_FIELD_ID = "ADD_AREA_POS_TEXT_FIELD_ID";
  67     public final static String ADD_INDEX_TEXT_FIELD_ID = "ADD_INDEX_TEXT_FIELD_ID";
  68     public final static String ADD_VALUE_TEXT_FIELD_ID = "ADD_VALUE_TEXT_FIELD_ID";
  69 
  70     public static void main(String[] args) {
  71         Utils.launch(NewLineChartApp.class, args);
  72     }
  73 
  74     @Override
  75     protected Scene getScene() {
  76         Utils.setTitleToStage(stage, "LineChartTestApp");
  77         return new NewLineChartApp.LineChartScene();
  78     }
  79 
  80     class LineChartScene extends CommonPropertiesScene {
  81 
  82         //LineChart to be tested.
  83         LineChart testedLineChart;        
  84         NumberAxis axis1;
  85         NumberAxis axis2;
  86         TabPaneWithControl pane;
  87 
  88         public LineChartScene() {
  89             super("LineChart", 1300, 800);
  90         }
  91 
  92         @Override
  93         final protected void prepareScene() {
  94             Utils.addBrowser(this);
  95 
  96             axis1 = new NumberAxis(0, 100, 10);
  97             axis2 = new NumberAxis(0, 100, 10);
  98             testedLineChart = getNewChart();
  99             testedLineChart.setId(TESTED_CHART_ID);
 100 
 101             Button hardResetButton = new Button("Hard reset");
 102             hardResetButton.setId(HARD_RESET_BUTTON_ID);
 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 = new Button("Soft reset");
 113             softResetButton.setId(SOFT_RESET_BUTTON_ID);
 114             softResetButton.setOnAction(new EventHandler<ActionEvent>() {
 115                 public void handle(ActionEvent t) {
 116                     //throw new UnsupportedOperationException("Not supported yet.");
 117                 }
 118             });
 119 
 120             HBox resetButtonsHBox = new HBox();
 121             resetButtonsHBox.getChildren().addAll(hardResetButton, softResetButton);
 122 
 123             VBox vb = new VBox(5);
 124             vb.getChildren().addAll(resetButtonsHBox, getAddLineHBox(), getAddPointToDataDialog(), getRemoveDataDialog(), getRemovePointFromDataDialog());
 125 
 126             pane = getPaneFor(testedLineChart, CHART_TAB_NAME, axis1, AXIS_1_TAB_NAME, axis2, AXIS_2_TAB_NAME);
 127 
 128             setTestedControlContainerSize(500, 500);
 129             setTestedControl(testedLineChart);
 130             setPropertiesContent(pane);
 131             setControllersContent(vb);
 132         }
 133 
 134         public HBox getAddPointToDataDialog() {
 135             HBox hb = new HBox();
 136 
 137             Label lb1 = new Label("To area");
 138             final TextField tf1 = new TextField("0");
 139             tf1.setPrefWidth(50);
 140             tf1.setId(ADD_LINE_POS_TEXT_FIELD_ID);
 141 
 142             Label lb2 = new Label("to index");
 143             final TextField tf2 = new TextField("0");
 144             tf2.setPrefWidth(50);
 145             tf2.setId(ADD_INDEX_TEXT_FIELD_ID);
 146 
 147             Label lb3 = new Label("value");
 148             final TextField tf3 = new TextField("0");
 149             tf3.setPrefWidth(50);
 150             tf3.setId(ADD_VALUE_TEXT_FIELD_ID);
 151 
 152             Button bt = new Button("add point!");
 153             bt.setId(REMOVE_BUTTON_ID);
 154             bt.setOnAction(new EventHandler() {
 155                 public void handle(Event t) {
 156                     int area = Integer.parseInt(tf1.getText());
 157                     int point = Integer.parseInt(tf2.getText());
 158                     double value = Double.parseDouble(tf3.getText());
 159 
 160                     XYChart.Data newData = new XYChart.Data();
 161                     newData.setXValue((((Double) ((XYChart.Data) (((XYChart.Series) testedLineChart.getData().get(area)).getData().get(point))).getXValue()) + ((Double) ((XYChart.Data) (((XYChart.Series) testedLineChart.getData().get(area)).getData().get(point - 1))).getXValue())) / 2);
 162                     newData.setYValue(value);
 163 
 164                     ((XYChart.Series) testedLineChart.getData().get(area)).getData().add(point, newData);
 165                 }
 166             });
 167             hb.getChildren().addAll(lb1, tf1, lb2, tf2, lb3, tf3, bt);
 168             return hb;
 169         }
 170 
 171         public HBox getRemovePointFromDataDialog() {
 172             HBox hb = new HBox();
 173 
 174             Label lb1 = new Label("From area");
 175             final TextField tf1 = new TextField("0");
 176             tf1.setPrefWidth(50);
 177             tf1.setId(REMOVE_LINE_FROM_POS_TEXT_FIELD_ID);
 178 
 179             Label lb2 = new Label("From index");
 180             final TextField tf2 = new TextField("0");
 181             tf2.setPrefWidth(50);
 182             tf2.setId(REMOVE_INDEX_TEXT_FIELD_ID);
 183 
 184             Button bt = new Button("remove point!");
 185             bt.setId(REMOVE_BUTTON_ID);
 186             bt.setOnAction(new EventHandler() {
 187                 public void handle(Event t) {
 188                     int area = Integer.parseInt(tf1.getText());
 189                     int point = Integer.parseInt(tf2.getText());
 190                     ((XYChart.Series) testedLineChart.getData().get(area)).getData().remove(point);
 191                 }
 192             });
 193             hb.getChildren().addAll(lb1, tf1, lb2, tf2, bt);
 194             return hb;
 195         }
 196 
 197         public HBox getRemoveDataDialog() {
 198             HBox hb = new HBox();
 199             Label lb = new Label("From index");
 200             final TextField tf = new TextField("0");
 201             tf.setPrefWidth(50);
 202             tf.setId(REMOVE_ITEM_POS_TEXT_FIELD_ID);
 203             Button bt = new Button("remove line!");
 204             bt.setId(REMOVE_BUTTON_ID);
 205             bt.setOnAction(new EventHandler() {
 206                 public void handle(Event t) {
 207                     int index = Integer.parseInt(tf.getText());
 208                     testedLineChart.getData().remove(index);
 209                 }
 210             });
 211             hb.getChildren().addAll(lb, tf, bt);
 212             return hb;
 213         }
 214 
 215         public HBox getAddLineHBox() {
 216             HBox hb = new HBox();
 217             Label lb = new Label("Add series named ");
 218             final TextField tf = new TextField();
 219             tf.setPrefWidth(50);
 220             tf.setId(ADDED_SERIES_NAME_TEXTFIELD_ID);
 221 
 222             Label minLabel = new Label(" minX ");
 223             final TextField minText = new TextField();
 224             minText.setPrefWidth(50);
 225             minText.setId(ADDED_SERIES_MIN_VALUE_TEXTFIELD_ID);
 226 
 227             Label maxLabel = new Label(" maxX ");
 228             final TextField maxText = new TextField();
 229             maxText.setPrefWidth(50);
 230             maxText.setId(ADDED_SERIES_MAX_VALUE_TEXTFIELD_ID);
 231 
 232             Label amountLabel = new Label(" with ");
 233             final TextField amountText = new TextField();
 234             amountText.setPrefWidth(50);
 235             amountText.setId(ADDED_SERIES_DOTS_COUNT_TEXTFIELD_ID);
 236 
 237             Button bt = new Button(" points add!");
 238             bt.setId(ADD_SERIES_COMMAND_BUTTON_ID);
 239             bt.setOnAction(new EventHandler() {
 240                 public void handle(Event t) {
 241                     String serieName = tf.getText();
 242                     double min = Double.parseDouble(minText.getText());
 243                     double max = Double.parseDouble(maxText.getText());
 244                     int amount = Integer.parseInt(amountText.getText());
 245 
 246                     ObservableList list = FXCollections.observableArrayList();
 247 
 248                     for (int i = 0; i < amount; i++) {
 249                         XYChart.Data newData = new XYChart.Data();
 250                         newData.setXValue(new Random().nextDouble() * (max - min) + min);
 251                         newData.setYValue(new Random().nextDouble() * (max - min) + min);
 252                         list.add(newData);
 253                     }
 254                     Object[] array = list.toArray();
 255                     Arrays.sort(array, new Comparator() {
 256                         public int compare(Object t, Object t1) {
 257                             return (int) Math.round(((Double) ((XYChart.Data) t).getXValue()) - ((Double) ((XYChart.Data) t1).getXValue()));
 258                         }
 259                     });
 260 
 261                     XYChart.Series serie = new XYChart.Series(serieName, FXCollections.observableArrayList(array));
 262 
 263                     testedLineChart.getData().add(serie);
 264                     pane.addPropertiesTable(serieName, getTableForProperty(serie, min, max).getVisualRepresentation());
 265                 }
 266             });
 267             hb.getChildren().addAll(lb, tf, minLabel, minText, maxLabel, maxText, amountLabel, amountText, bt);
 268             return hb;
 269         }
 270 
 271         protected PropertiesTable getTableForProperty(XYChart.Series serie, double min, double max) {
 272             PropertiesTable table = new PropertiesTable(serie);
 273 
 274             table.addSimpleListener(serie.chartProperty(), serie);
 275             table.addSimpleListener(serie.nameProperty(), serie);
 276             table.addSimpleListener(serie.dataProperty(), serie);
 277 
 278             for (Iterator it = serie.getData().iterator(); it.hasNext();) {
 279                 final XYChart.Data data = (XYChart.Data) it.next();
 280 
 281                 final DoubleProperty intermediateX = new SimpleDoubleProperty(null, "XValue");
 282                 final DoubleProperty intermediateY = new SimpleDoubleProperty(null, "YValue");
 283 
 284                 data.XValueProperty().addListener(new ChangeListener() {
 285                     public void changed(ObservableValue ov, Object t, Object t1) {
 286                         if (!intermediateX.isBound()) {
 287                             intermediateX.setValue((Double) data.XValueProperty().getValue());
 288                         }
 289                     }
 290                 });
 291 
 292                 data.YValueProperty().addListener(new ChangeListener() {
 293                     public void changed(ObservableValue ov, Object t, Object t1) {
 294                         if (!intermediateY.isBound()) {
 295                             intermediateY.setValue((Double) data.YValueProperty().getValue());
 296                         }
 297                     }
 298                 });
 299 
 300                 intermediateX.addListener(new ChangeListener() {
 301                     public void changed(ObservableValue ov, Object t, Object t1) {
 302                         data.setXValue(t1);
 303                     }
 304                 });
 305 
 306                 intermediateY.addListener(new ChangeListener() {
 307                     public void changed(ObservableValue ov, Object t, Object t1) {
 308                         data.setYValue(t1);
 309                     }
 310                 });
 311 
 312                 table.addDoublePropertyLine(intermediateX, min, max, (Double) data.getXValue(), data);
 313                 table.addDoublePropertyLine(intermediateY, min, max, (Double) data.getYValue(), data);
 314             }
 315 
 316             return table;
 317         }
 318 
 319         public LineChart getNewChart() {
 320             LineChart chart = new LineChart(axis1, axis2);
 321             chart.setTitle("LineChart");
 322             chart.setStyle("-fx-border-color: darkgray;");
 323             return chart;
 324         }
 325     }
 326 }