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