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.treeview;
  26 
  27 import java.util.ArrayList;
  28 import static javafx.commons.Consts.BTN_SET_ON_EDIT_EVENT_HANDLERS;
  29 import javafx.event.ActionEvent;
  30 import javafx.event.Event;
  31 import javafx.event.EventHandler;
  32 import javafx.geometry.Orientation;
  33 import javafx.scene.Scene;
  34 import javafx.scene.control.*;
  35 import javafx.scene.control.test.treetable.ResetButtonNames;
  36 import static javafx.scene.control.test.treetable.ResetButtonNames.HARD_RESET_BUTTON_ID;
  37 import static javafx.scene.control.test.treetable.ResetButtonNames.SOFT_RESET_BUTTON_ID;
  38 import static javafx.scene.control.test.treeview.TreeViewConstants.ROOT_NAME;
  39 import javafx.scene.control.test.utils.CommonPropertiesScene;
  40 import javafx.scene.control.test.utils.ptables.NodeControllerFactory;
  41 import javafx.scene.control.test.utils.ptables.NodeControllerFactory.NodesStorage;
  42 import javafx.scene.control.test.utils.ptables.PropertiesTable;
  43 import javafx.scene.control.test.utils.ptables.PropertyTablesFactory;
  44 import javafx.scene.control.test.utils.ptables.SpecialTablePropertiesProvider;
  45 import javafx.scene.control.test.utils.ptables.TabPaneWithControl;
  46 import javafx.scene.input.KeyCode;
  47 import javafx.scene.input.KeyEvent;
  48 import javafx.scene.layout.HBox;
  49 import javafx.scene.layout.VBox;
  50 import javafx.util.Callback;
  51 import test.javaclient.shared.InteroperabilityApp;
  52 import test.javaclient.shared.Utils;
  53 
  54 /**
  55  * @author Alexander Kirov
  56  */
  57 public class TreeViewNewApp extends InteroperabilityApp implements TreeViewConstants, ResetButtonNames {
  58 
  59     public final static String TESTED_TREEVIEW_ID = "TESTED_TREEVIEW_ID";
  60     public final static String POPULATE_TREE = "POPULATE_TREE";
  61     public final static String TREE_VIEW_TAB_NAME = "TreeView";
  62 
  63     public static void main(String[] args) {
  64         Utils.launch(TreeViewNewApp.class, args);
  65     }
  66 
  67     @Override
  68     protected Scene getScene() {
  69         Scene scene = new TreeViewScene();
  70         Utils.addBrowser(scene);
  71         Utils.setTitleToStage(stage, "TreeViewTestApp");
  72         return scene;
  73     }
  74 
  75     public static TreeItem searchTreeItem(TreeView treeView, String content) {
  76         if (treeView.getRoot() != null) {
  77             return recursiveSearch(content, treeView.getRoot());
  78         }
  79         return null;
  80     }
  81 
  82     protected static TreeItem recursiveSearch(String content, TreeItem<? extends Object> itemToStart) {
  83         if (content.equals(itemToStart.getValue())) {
  84             return itemToStart;
  85         } else {
  86             for (TreeItem child : itemToStart.getChildren()) {
  87                 TreeItem recResult = recursiveSearch(content, child);
  88                 if (recResult != null) {
  89                     return recResult;
  90                 }
  91             }
  92             return null;
  93         }
  94     }
  95 
  96     protected class TreeViewScene extends CommonPropertiesScene {
  97 
  98         TreeView testedControl;
  99         //TabPane with PropertiesTable.
 100         TabPaneWithControl tabPane;
 101         PropertiesTable tb;
 102         //This list contains all properties tables, which were created during testing.
 103         ArrayList<PropertiesTable> allPropertiesTables;
 104 
 105         public TreeViewScene() {
 106             super("TreeView", 800, 600);
 107             prepareScene();
 108         }
 109 
 110         protected TreeView getNewTestedControl() {
 111             TreeView tv = new TreeView(new TreeItem(ROOT_NAME));
 112             tv.setId(TESTED_TREEVIEW_ID);
 113             return tv;
 114         }
 115 
 116         @Override
 117         final protected void prepareScene() {
 118             testedControl = getNewTestedControl();
 119             tb = new PropertiesTable(testedControl);
 120 
 121             allPropertiesTables = new ArrayList<PropertiesTable>();
 122             allPropertiesTables.add(tb);
 123 
 124             PropertyTablesFactory.explorePropertiesList(testedControl, tb);
 125             PropertyTablesFactory.explorePropertiesList(testedControl.getSelectionModel(), tb);
 126             PropertyTablesFactory.explorePropertiesList(testedControl.getFocusModel(), tb);
 127             SpecialTablePropertiesProvider.provideForControl(testedControl, tb);
 128 
 129             tb.addCounter(EDIT_START_COUNTER);
 130             tb.addCounter(EDIT_COMMIT_COUNTER);
 131             tb.addCounter(EDIT_CANCEL_COUNTER);
 132 
 133             tabPane = new TabPaneWithControl("TreeView", tb);
 134             getControlOverItem(ROOT_NAME);
 135 
 136             Button hardResetButton = new Button("Hard reset");
 137             hardResetButton.setId(HARD_RESET_BUTTON_ID);
 138             hardResetButton.setOnAction(new EventHandler<ActionEvent>() {
 139                 public void handle(ActionEvent t) {
 140                     HBox hb = (HBox) getRoot();
 141                     hb.getChildren().clear();
 142                     prepareMainSceneStructure();
 143                     prepareScene();
 144                 }
 145             });
 146 
 147             Button softResetButton = new Button("Soft reset");
 148             softResetButton.setId(SOFT_RESET_BUTTON_ID);
 149             softResetButton.setOnAction(new EventHandler<ActionEvent>() {
 150                 public void handle(ActionEvent t) {
 151                     refreshProcedure(2);
 152                     testedControl.getRoot().setValue(ROOT_NAME);
 153                     TreeItem someNewOneTreeItem = new TreeItem();
 154                     testedControl.getRoot().setExpanded(someNewOneTreeItem.isExpanded());
 155                     testedControl.getRoot().setGraphic(someNewOneTreeItem.getGraphic());
 156 
 157                     TreeView someNewOneTreeView = new TreeView();
 158                     testedControl.setDisable(someNewOneTreeView.isDisabled());
 159                     testedControl.setEditable(someNewOneTreeView.isEditable());
 160                     testedControl.setShowRoot(someNewOneTreeView.isShowRoot());
 161                     testedControl.getSelectionModel().setSelectionMode(someNewOneTreeView.getSelectionModel().getSelectionMode());
 162                     testedControl.setMinHeight(someNewOneTreeView.getMinHeight());
 163                     testedControl.setMinWidth(someNewOneTreeView.getMinWidth());
 164                     testedControl.setPrefHeight(someNewOneTreeView.getPrefHeight());
 165                     testedControl.setPrefWidth(someNewOneTreeView.getPrefWidth());
 166                 }
 167             });
 168 
 169             Button populate = new Button("Populate");
 170             populate.setId(POPULATE_TREE);
 171             populate.setOnAction(new EventHandler<ActionEvent>() {
 172 
 173                 public void handle(ActionEvent t) {
 174                     TreeItem root = new TreeItem("ROOT");
 175                     root.setExpanded(true);
 176                     for (int i = 0; i < 4; i++) {
 177                         TreeItem parent = new TreeItem("item-" + String.valueOf(i));
 178                         parent.setExpanded(true);
 179                         root.getChildren().add(parent);
 180                         for (int j = 0; j < 4; j++) {
 181                             TreeItem child = new TreeItem("item-" + String.valueOf(i) + "-" + String.valueOf(j));
 182                             parent.getChildren().add(child);
 183                         }
 184                     }
 185                     testedControl.setRoot(root);
 186                 }
 187             });
 188 
 189             HBox hboxWithResetButtons = new HBox();
 190             hboxWithResetButtons.getChildren().addAll(hardResetButton, softResetButton, populate);
 191 
 192             Button autosize = new Button("Autosize");
 193             autosize.setId(AUTOSIZE_BUTTON_ID);
 194             autosize.setOnAction(new EventHandler<ActionEvent>() {
 195                 public void handle(ActionEvent t) {
 196                     testedControl.autosize();
 197                 }
 198             });
 199 
 200             VBox vb = new VBox();
 201             vb.setSpacing(5);
 202             //Different action makers.
 203             vb.getChildren().addAll(hboxWithResetButtons, autosize, new Separator(Orientation.HORIZONTAL),
 204                     getTreeViewAddItemController(), new Separator(Orientation.HORIZONTAL),
 205                     getTreeViewRemoveItemController(), new Separator(Orientation.HORIZONTAL),
 206                     getTabOverItemThroughGetItemMethodController(), new Separator(Orientation.HORIZONTAL),
 207                     getTabOverItemController(), new Separator(Orientation.HORIZONTAL),
 208                     getObjectTitleThroughGetItemMethodController(), new Separator(Orientation.HORIZONTAL),
 209                     getLineOfItemController(), new Separator(Orientation.HORIZONTAL),
 210                     getScrollToHBox(), new Separator(Orientation.HORIZONTAL),
 211                     getEditHBox(), new Separator(Orientation.HORIZONTAL),
 212                     setEventHandlersHBox());
 213 
 214             setTestedControl(testedControl);
 215             setPropertiesContent(tabPane);
 216             setControllersContent(vb);
 217         }
 218 
 219         /*
 220          * In this function TabPane with control will be refreshed, and all 
 221          * properties table will be refreshed and cleared.
 222          */
 223         private void refreshProcedure(int exceptFirstPropertiesTable) {
 224             for (int i = allPropertiesTables.size() - 1; i >= 0; i--) {
 225                 allPropertiesTables.get(i).refresh();
 226                 if (i >= exceptFirstPropertiesTable) {
 227                     allPropertiesTables.remove(i);
 228                 }
 229             }
 230 
 231             tabPane.removePropertiesTablesExceptFirstOnes(exceptFirstPropertiesTable);
 232 
 233             testedControl.getRoot().getChildren().clear();
 234         }
 235 
 236         protected void getControlOverItem(String name) {
 237             TreeItem treeItem = searchTreeItem(name);
 238             NodesStorage node = NodeControllerFactory.createFullController(treeItem, tabPane);
 239             allPropertiesTables.add(node.pt);
 240             tabPane.addPropertiesTable(name, node);
 241         }
 242 
 243         protected VBox getTreeViewAddItemController() {
 244             VBox vb = new VBox(3);
 245 
 246             final TextField tfParentName = new TextField();
 247             tfParentName.setId(ADD_ITEM_PARENT_TEXT_FIELD_ID);
 248             tfParentName.setPromptText("parent name");
 249 
 250             final TextField tfName = new TextField();
 251             tfName.setId(ADD_ITEM_TEXT_FIELD_ID);
 252             tfName.setPromptText("new item name");
 253 
 254             final TextField tfPosition = new TextField();
 255             tfPosition.setId(ADD_ITEM_POSITION_TEXT_FIELD_ID);;
 256             tfPosition.setPromptText("position");
 257             tfPosition.setPrefWidth(50);
 258 
 259             Button button = new Button("add to pos");
 260             button.setId(ADD_ITEM_BUTTON_ID);
 261             button.setOnAction(new EventHandler<ActionEvent>() {
 262                 public void handle(ActionEvent t) {
 263                     TreeItem treeItem = searchTreeItem(tfParentName.getText());
 264                     treeItem.getChildren().add(Integer.parseInt(tfPosition.getText()), new TreeItem(tfName.getText()));
 265                 }
 266             });
 267 
 268             HBox hb1 = new HBox(3);
 269             hb1.getChildren().addAll(new Label("Add child to "), tfParentName);
 270 
 271             HBox hb2 = new HBox(3);
 272             hb2.getChildren().addAll(new Label(" named "), tfName);
 273 
 274             HBox hb3 = new HBox(3);
 275             hb3.getChildren().addAll(tfPosition, button);
 276 
 277             vb.getChildren().addAll(hb1, hb2, hb3);
 278 
 279             return vb;
 280         }
 281 
 282         protected VBox getTreeViewRemoveItemController() {
 283             VBox vb = new VBox(3);
 284 
 285             final TextField tfName = new TextField();
 286             tfName.setId(REMOVE_ITEM_TEXT_FIELD_ID);
 287             tfName.setPromptText("new item name");
 288 
 289             Button button = new Button("remove!");
 290             button.setId(REMOVE_ITEM_BUTTON_ID);
 291             button.setOnAction(new EventHandler<ActionEvent>() {
 292                 public void handle(ActionEvent t) {
 293                     TreeItem treeItem = searchTreeItem(tfName.getText());
 294                     treeItem.getParent().getChildren().remove(treeItem);
 295                 }
 296             });
 297 
 298             HBox hb1 = new HBox(3);
 299             hb1.getChildren().addAll(new Label("Named item"), tfName);
 300 
 301             HBox hb2 = new HBox(3);
 302             hb2.getChildren().addAll(button);
 303 
 304             vb.getChildren().addAll(hb1, hb2);
 305 
 306             return vb;
 307         }
 308 
 309         protected VBox getTabOverItemController() {
 310             final TextField tfParentName = new TextField();
 311             tfParentName.setId(GET_CONTROL_OVER_TREEITEM_TEXTFIELD_ID);
 312             tfParentName.setPromptText("item name");
 313 
 314             Button button = new Button("get table over");
 315             button.setId(GET_CONTROL_OVER_TREEITEM_BUTTON_ID);
 316             button.setOnAction(new EventHandler<ActionEvent>() {
 317                 public void handle(ActionEvent t) {
 318                     getControlOverItem(tfParentName.getText());
 319                 }
 320             });
 321 
 322             HBox hb1 = new HBox(3);
 323             hb1.getChildren().addAll(tfParentName, button);
 324 
 325             VBox vb = new VBox();
 326             vb.getChildren().addAll(hb1);
 327             return vb;
 328         }
 329 
 330         protected VBox getObjectTitleThroughGetItemMethodController() {
 331             final TextField tfParentName = new TextField();
 332             tfParentName.setPromptText("index");
 333             tfParentName.setPrefWidth(50);
 334 
 335             final TextField content = new TextField();
 336             content.setPromptText("content");
 337 
 338             Button button = new Button("getTreeItem! index:");
 339             button.setOnAction(new EventHandler<ActionEvent>() {
 340                 public void handle(ActionEvent t) {
 341                     TreeItem item = testedControl.getTreeItem(Integer.parseInt(tfParentName.getText()));
 342                     if (item == null) {
 343                         content.setText("null");
 344                     } else {
 345                         content.setText(item.getValue().toString());
 346                     }
 347                 }
 348             });
 349 
 350             HBox hb1 = new HBox(3);
 351             hb1.getChildren().addAll(new Label("Get tree item at"), tfParentName);
 352 
 353             HBox hb2 = new HBox(3);
 354             hb2.getChildren().addAll(button, content);
 355 
 356             VBox vb = new VBox();
 357             vb.getChildren().addAll(hb1, hb2);
 358             return vb;
 359         }
 360 
 361         protected VBox getTabOverItemThroughGetItemMethodController() {
 362             final TextField tfParentName = new TextField();
 363             tfParentName.setPromptText("index");
 364             tfParentName.setPrefWidth(50);
 365 
 366             Button button = new Button("get table over");
 367             button.setOnAction(new EventHandler<ActionEvent>() {
 368                 public void handle(ActionEvent t) {
 369                     getControlOverItem(testedControl.getTreeItem(Integer.parseInt(tfParentName.getText())).getValue().toString());
 370                 }
 371             });
 372 
 373             HBox hb1 = new HBox(3);
 374             hb1.getChildren().addAll(tfParentName, button);
 375 
 376             VBox vb = new VBox();
 377             vb.getChildren().addAll(hb1);
 378             return vb;
 379         }
 380 
 381         protected VBox getLineOfItemController() {
 382             final TextField tfParentName = new TextField();
 383             tfParentName.setPromptText("name");
 384 
 385             final TextField index = new TextField();
 386             index.setPromptText("found index");
 387             index.setPrefWidth(50);
 388 
 389             Button button = new Button("getRow! index :");
 390             button.setOnAction(new EventHandler<ActionEvent>() {
 391                 public void handle(ActionEvent t) {
 392                     int found = testedControl.getRow(searchTreeItem(tfParentName.getText()));
 393                     index.setText(((Integer) found).toString());
 394                 }
 395             });
 396 
 397             HBox hb1 = new HBox(3);
 398             hb1.getChildren().addAll(new Label("Get index of"), tfParentName);
 399 
 400             HBox hb2 = new HBox(3);
 401             hb2.getChildren().addAll(index, button);
 402 
 403             VBox vb = new VBox();
 404             vb.getChildren().addAll(hb1, hb2);
 405             return vb;
 406         }
 407 
 408         private HBox getScrollToHBox() {
 409             HBox hb = new HBox();
 410             Button button = new Button("ScrollTo");
 411             button.setId(SCROLL_TO_BUTTON_ID);
 412             final TextField tf = new TextField("0");
 413             tf.setId(SCROLL_TO_TEXT_FIELD_ID);
 414             tf.setPrefWidth(50);
 415 
 416             button.setOnAction(new EventHandler<ActionEvent>() {
 417                 public void handle(ActionEvent t) {
 418                     testedControl.scrollTo(Integer.parseInt(tf.getText()));
 419                 }
 420             });
 421 
 422             hb.getChildren().addAll(tf, button);
 423             return hb;
 424         }
 425 
 426         private HBox getEditHBox() {
 427             HBox hb = new HBox();
 428             Button button = new Button("Edit");
 429             button.setId(EDIT_BUTTON_ID);
 430             final TextField tf = new TextField();
 431             tf.setPromptText("name");
 432             tf.setId(EDIT_TEXT_FIELD_ID);
 433             tf.setPrefWidth(50);
 434 
 435             button.setOnAction(new EventHandler<ActionEvent>() {
 436                 public void handle(ActionEvent t) {
 437                     testedControl.edit(searchTreeItem(tf.getText()));
 438                 }
 439             });
 440 
 441             hb.getChildren().addAll(tf, button);
 442             return hb;
 443         }
 444 
 445         private VBox setEventHandlersHBox() {
 446             VBox vb = new VBox();
 447 
 448             Button btn = new Button("Set onEdit event hadlers");
 449             btn.setId(BTN_SET_ON_EDIT_EVENT_HANDLERS);
 450             btn.setOnAction(new EventHandler<ActionEvent>() {
 451                 public void handle(ActionEvent t) {
 452                     testedControl.setOnEditStart(new EventHandler() {
 453                         public void handle(Event t) {
 454                             tb.incrementCounter(EDIT_START_COUNTER);
 455                         }
 456                     });
 457 
 458                     testedControl.setOnEditCommit(new EventHandler() {
 459                         public void handle(Event t) {
 460                             tb.incrementCounter(EDIT_COMMIT_COUNTER);
 461                         }
 462                     });
 463 
 464                     testedControl.setOnEditCancel(new EventHandler() {
 465                         public void handle(Event t) {
 466                             tb.incrementCounter(EDIT_CANCEL_COUNTER);
 467                         }
 468                     });
 469                 }
 470             });
 471 
 472             Button btnAddFactory = new Button("Set cell factory for editing");
 473             btnAddFactory.setId(SET_CELL_FACTORY_FOR_EDITING);
 474             btnAddFactory.setOnAction(new EventHandler<ActionEvent>() {
 475                 public void handle(ActionEvent t) {
 476                     testedControl.setCellFactory(new Callback<TreeView<String>, TreeCell<String>>() {
 477                         @Override
 478                         public TreeCell<String> call(TreeView<String> p) {
 479                             return new TextFieldTreeCellImpl();
 480                         }
 481                     });
 482                 }
 483             });
 484 
 485             vb.getChildren().addAll(btn, btnAddFactory);
 486             return vb;
 487         }
 488 
 489         private TreeItem searchTreeItem(String content) {
 490             return TreeViewNewApp.searchTreeItem(testedControl, content);
 491         }
 492 
 493         private final class TextFieldTreeCellImpl extends TreeCell<String> {
 494 
 495             private TextField textField;
 496 
 497             public TextFieldTreeCellImpl() {
 498             }
 499 
 500             @Override
 501             public void startEdit() {
 502                 super.startEdit();
 503 
 504                 if (textField == null) {
 505                     createTextField();
 506                 }
 507                 setText(null);
 508                 setGraphic(textField);
 509                 textField.setText(getString());
 510                 textField.requestFocus();
 511             }
 512 
 513             @Override
 514             public void cancelEdit() {
 515                 super.cancelEdit();
 516                 setText((String) getItem());
 517                 setGraphic(getTreeItem().getGraphic());
 518             }
 519 
 520             @Override
 521             public void updateItem(String item, boolean empty) {
 522                 super.updateItem(item, empty);
 523 
 524                 if (empty) {
 525                     setText(null);
 526                     setGraphic(null);
 527                 } else {
 528                     if (isEditing()) {
 529                         if (textField != null) {
 530                             textField.setText(getString());
 531                         }
 532                         setText(null);
 533                         setGraphic(textField);
 534                     } else {
 535                         setText(getString());
 536                         setGraphic(getTreeItem().getGraphic());
 537                     }
 538                 }
 539             }
 540 
 541             private void createTextField() {
 542                 textField = new TextField(getString());
 543                 textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
 544                     @Override
 545                     public void handle(KeyEvent t) {
 546                         if (t.getCode() == KeyCode.ENTER) {
 547                             commitEdit(textField.getText());
 548                         } else if (t.getCode() == KeyCode.ESCAPE) {
 549                             cancelEdit();
 550                         }
 551                     }
 552                 });
 553             }
 554 
 555             private String getString() {
 556                 return getItem() == null ? "" : getItem().toString();
 557             }
 558         }
 559     }
 560 }