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.tableview;
  26 
  27 import com.sun.javafx.scene.control.skin.NestedTableColumnHeader;
  28 import com.sun.javafx.scene.control.skin.TableColumnHeader;
  29 import java.util.Collection;
  30 import java.util.Comparator;
  31 import java.util.concurrent.TimeUnit;
  32 import java.util.logging.Level;
  33 import java.util.logging.Logger;
  34 import javafx.collections.FXCollections;
  35 import static javafx.commons.Consts.*;
  36 import static javafx.commons.Consts.Cell.EDITING_CHOICEBOX_CELL_ID;
  37 import javafx.commons.Consts.CellEditorType;
  38 import javafx.scene.Node;
  39 import javafx.scene.Scene;
  40 import javafx.scene.control.CheckBox;
  41 import javafx.scene.control.ComboBox;
  42 import javafx.scene.control.Control;
  43 import javafx.scene.control.Label;
  44 import javafx.scene.control.Labeled;
  45 import javafx.scene.control.ScrollBar;
  46 import javafx.scene.control.TableCell;
  47 import javafx.scene.control.TableColumnBase;
  48 import javafx.scene.control.TableView;
  49 import javafx.scene.control.TextField;
  50 import javafx.scene.control.TreeTableView;
  51 import static javafx.scene.control.test.treetable.ResetButtonNames.HARD_RESET_BUTTON_ID;
  52 import static javafx.scene.control.test.treetable.ResetButtonNames.SOFT_RESET_BUTTON_ID;
  53 import javafx.scene.control.test.treetable.TreeTableNewApp;
  54 import javafx.scene.control.test.utils.ptables.AbstractPropertyController.SettingType;
  55 import javafx.stage.PopupWindow;
  56 import org.jemmy.Point;
  57 import org.jemmy.Rectangle;
  58 import org.jemmy.action.GetAction;
  59 import org.jemmy.control.Wrap;
  60 import org.jemmy.env.Environment;
  61 import org.jemmy.fx.ByID;
  62 import org.jemmy.fx.ByWindowType;
  63 import org.jemmy.fx.Root;
  64 import org.jemmy.interfaces.Parent;
  65 import org.jemmy.lookup.Lookup;
  66 import org.jemmy.lookup.LookupCriteria;
  67 import org.jemmy.timing.State;
  68 import org.junit.After;
  69 import org.junit.Before;
  70 import org.junit.BeforeClass;
  71 
  72 /**
  73  * @author Alexander Kirov
  74  */
  75 public class ApplicationInteractionFunctions extends TestBaseCommon {
  76 
  77     protected static Wrap<? extends Scene> scene;
  78     protected static Wrap<? extends Control> testedControl;
  79     protected static boolean isTableTests = true;
  80 
  81     protected boolean resetHardByDefault = true;//switcher of hard and soft reset mode.
  82     protected boolean doNextResetHard = resetHardByDefault;
  83 
  84     protected static enum Properties {
  85 
  86         prefWidth, prefHeight, width, sortNode, comparator, sortOrder, graphic,
  87         resizable, showRoot, expanded, editable, value, sortable, fixedCellSize, reorderable};
  88 
  89     @BeforeClass
  90     public static void setUpClass() throws Exception {
  91         if (isTableTests) {
  92             System.out.println("Starting a TableView application with properties control.");
  93             NewTableViewApp.main(null);
  94         } else {
  95             System.out.println("Starting a TreeTable application with properties control.");
  96             TreeTableNewApp.main(null);
  97         }
  98     }
  99 
 100     @Before
 101     public void setUp() {
 102         initWrappers();
 103         Environment.getEnvironment().setTimeout("wait.state", 2000);
 104         Environment.getEnvironment().setTimeout("wait.control", 1000);
 105         scene.mouse().move(new Point(0, 0));
 106     }
 107 
 108     @After
 109     public void tearDown() {
 110         if (doNextResetHard) {
 111             resetSceneHard();
 112         } else {
 113             resetSceneSoft();
 114         }
 115 
 116         doNextResetHard = resetHardByDefault;
 117         currentSettingOption = SettingOption.PROGRAM;
 118     }
 119 
 120     protected void initWrappers() {
 121         scene = Root.ROOT.lookup().wrap();
 122         parent = scene.as(Parent.class, Node.class);
 123         if (isTableTests) {
 124             testedControl = parent.lookup(TableView.class, new ByID<TableView>(NewTableViewApp.TESTED_TABLE_VIEW_ID)).wrap();
 125         } else {
 126             testedControl = parent.lookup(TreeTableView.class, new ByID<TreeTableView>(TreeTableNewApp.TESTED_TREETABLEVIEW_ID)).wrap();
 127         }
 128     }
 129 
 130     /**
 131      * Set size if tested control using bidirectional bindings.
 132      */
 133     protected void setSize(double width, double height) throws InterruptedException {
 134         setPropertyBySlider(SettingType.BIDIRECTIONAL, Properties.prefHeight, height);
 135         setPropertyBySlider(SettingType.BIDIRECTIONAL, Properties.prefWidth, width);
 136     }
 137 
 138     protected void setNewDataSize(int newSize) {
 139         setText(findTextField(NEW_DATA_SIZE_TEXTFIELD_ID), String.valueOf(newSize));
 140         clickButtonForTestPurpose(NEW_DATA_SIZE_BUTTON_ID);
 141     }
 142 
 143     public static void addColumn(String name, int index) {
 144         addColumn(name, index, false);
 145     }
 146 
 147     public static void addColumn(String name, int index, boolean createPropertiesTab) {
 148         setText(findTextField(NEW_COLUMN_NAME_TEXTFIELD_ID), name);
 149         setText(findTextField(NEW_COLUMN_INDEX_TEXTFIELD_UD), String.valueOf(index));
 150         setCheckBoxState(NEW_COLUMN_GET_COLUMN_PROPERTIES_TAB_ID, createPropertiesTab);
 151         clickButtonForTestPurpose(NEW_COLUMN_ADD_BUTTON_ID);
 152     }
 153 
 154     protected void createNestedColumn(String newColumnName, int index, int... indicesOfColumns) {
 155         setText(findTextField(NESTED_COLUMN_NAME_TEXT_FIELD_ID), newColumnName);
 156         setText(findTextField(NESTED_COLUMN_INDEX_TEXT_FIELD_ID), String.valueOf(index));
 157         setText(findTextField(CREATE_NESTED_COLUMN_MULTIPLE_TEXTFIELD_ID), convertMultiIndicesToString(indicesOfColumns));
 158         clickButtonForTestPurpose(CREATE_NESTED_COLUMN_MULTIPLE_ACTION_BUTTON_ID);
 159     }
 160 
 161     protected void removeColumns(int... indicesOfColumns) {
 162         setText(findTextField(REMOVE_MULTIPLE_COLUMNS_TEXT_FIELD_ID), convertMultiIndicesToString(indicesOfColumns));
 163         clickButtonForTestPurpose(REMOVE_MULTIPLE_COLUMNS_ACTION_BUTTON_ID);
 164     }
 165 
 166     protected void removeDataItems(int... indicesOfColumns) {
 167         setText(findTextField(REMOVE_DATA_ITEMS_MULTIPLE_TEXT_FIELD_ID), convertMultiIndicesToString(indicesOfColumns));
 168         clickButtonForTestPurpose(REMOVE_DATA_ITEMS_MULTIPLE_ACTION_BUTTON_ID);
 169     }
 170 
 171     private void resetSceneHard() {
 172         clickButtonForTestPurpose(HARD_RESET_BUTTON_ID);
 173         initWrappers();
 174     }
 175 
 176     private void resetSceneSoft() {
 177         clickButtonForTestPurpose(SOFT_RESET_BUTTON_ID);
 178         initWrappers();
 179     }
 180 
 181     protected void scrollTo(final int column, final int row) {
 182         scrollTo(testedControl, column, row);
 183     }
 184 
 185     protected Wrap<? extends TableCell> getCellWrap(final int column, final int row) {
 186         return getCellWrap(testedControl, column, row);
 187     }
 188 
 189     protected Point getResizingPointOfColumn(String columnName) {
 190         Rectangle rec = getTableColumnHeaderWrap(columnName).getScreenBounds();
 191         return new Point(rec.x + rec.width, rec.y + rec.height / 2);
 192     }
 193 
 194     protected double getScrollBarValue(final Wrap<? extends ScrollBar> scroll) {
 195         return new GetAction<Double>() {
 196             @Override
 197             public void run(Object... os) throws Exception {
 198                 setResult(scroll.getControl().getValue());
 199             }
 200         }.dispatch(Root.ROOT.getEnvironment());
 201     }
 202 
 203     protected Wrap<? extends TableColumnHeader> getTableColumnHeaderWrap(final String name) {
 204         return testedControl.as(Parent.class, Node.class).lookup(TableColumnHeader.class, new LookupCriteria<TableColumnHeader>() {
 205             public boolean check(TableColumnHeader cntrl) {
 206                 if ((cntrl.getBoundsInLocal().getMaxY() > 15) && (!(cntrl instanceof NestedTableColumnHeader))) {
 207                     return ((Label) (cntrl.getChildrenUnmodifiable().get(0))).getText().equals(name);
 208                 } else {
 209                     return false;
 210                 }
 211             }
 212         }).wrap();
 213     }
 214 
 215     /*
 216      * Clears all the content and then
 217      * creates COLS columns and respective numver of rows
 218      * with different string literals;
 219      * @param COLS number of columns
 220      */
 221     void createRowsForSortPurposes(final int COLS) {
 222         Integer colsCount = new GetAction<Integer>() {
 223             @Override
 224             public void run(Object... parameters) throws Exception {
 225                 if (isTableTests) {
 226                     TableView tv = (TableView) testedControl.getControl();
 227                     setResult(Integer.valueOf(tv.getColumns().size()));
 228                 } else {
 229                     TreeTableView ttv = (TreeTableView) testedControl.getControl();
 230                     setResult(Integer.valueOf(ttv.getColumns().size()));
 231                     ttv.setShowRoot(false);
 232                 }
 233             }
 234         }.dispatch(testedControl.getEnvironment());
 235 
 236         //Remove columns if exist
 237         if (colsCount.intValue() > 0) {
 238             StringBuilder sb = new StringBuilder();
 239             for (int i = 0; i < colsCount.intValue(); i++) {
 240                 if (0 != i) {
 241                     sb.append(";");
 242                 }
 243                 sb.append(i);
 244             }
 245 
 246             Wrap wrap = parent.lookup(TextField.class, new ByID(REMOVE_MULTIPLE_COLUMNS_TEXT_FIELD_ID)).wrap();
 247             setText(wrap, sb.toString());
 248             clickButtonForTestPurpose(REMOVE_MULTIPLE_COLUMNS_ACTION_BUTTON_ID);
 249         }
 250 
 251         Wrap wrap = parent.lookup(CheckBox.class, new ByID(NEW_COLUMN_GET_COLUMN_PROPERTIES_TAB_ID)).wrap();
 252         wrap.mouse().click();
 253 
 254         for (int i = 0; i < COLS; i++) {
 255             wrap = parent.lookup(TextField.class, new ByID(NEW_COLUMN_NAME_TEXTFIELD_ID)).wrap();
 256 
 257             String tabName = String.format("column %d", i);
 258             setText(wrap, tabName);
 259 
 260             wrap = parent.lookup(TextField.class, new ByID(NEW_COLUMN_INDEX_TEXTFIELD_UD)).wrap();
 261             setText(wrap, String.valueOf(i));
 262 
 263             clickButtonForTestPurpose(NEW_COLUMN_ADD_BUTTON_ID);
 264             switchToPropertiesTab(tabName);
 265             try {
 266                 setPropertyBySlider(SettingType.SETTER, Properties.prefWidth, 50.0);
 267             } catch (InterruptedException ex) {
 268                 Logger.getLogger(ApplicationInteractionFunctions.class.getName()).log(Level.SEVERE, null, ex);
 269             }
 270         }
 271 
 272         clickButtonForTestPurpose(BTN_CREATE_SORTABLE_ROWS_ID);
 273     }
 274 
 275     protected void setCellEditor(final CellEditorType type, final boolean isCustom) {
 276 
 277         new GetAction<Object>() {
 278             @Override
 279             public void run(Object... parameters) throws Exception {
 280                 Wrap<? extends Node> cmbEditors
 281                         = parent.lookup(new ByID(CMB_EDITORS_ID)).wrap();
 282 
 283                 ((ComboBox) cmbEditors.getControl()).setValue(type);
 284             }
 285         }.dispatch(testedControl.getEnvironment());
 286 
 287         new GetAction<Object>() {
 288             @Override
 289             public void run(Object... parameters) throws Exception {
 290                 Wrap<? extends Node> chbCustom = parent.lookup(new ByID(CHB_IS_CUSTOM_ID)).wrap();
 291                 ((CheckBox)chbCustom.getControl()).setSelected(isCustom);
 292             }
 293         }.dispatch(testedControl.getEnvironment());
 294 
 295         clickButtonForTestPurpose(BTN_SET_CELLS_EDITOR_ID);
 296 
 297         if (isCustom) {
 298             testedControl.waitState(new State<Object>() {
 299                 String id = null;
 300                 {
 301                    if (type == CellEditorType.CHOICEBOX) {
 302                         id = Cell.EDITING_CHOICEBOX_CELL_ID;
 303                     } else if (type == CellEditorType.COMBOBOX) {
 304                         id = Cell.EDITING_COMBOBOX_CELL_ID;
 305                     } else if (type == CellEditorType.TEXT_FIELD) {
 306                         id = Cell.EDITING_TEXTFIELD_CELL_ID;
 307                     } else {
 308                         throw new RuntimeException("Something went wrong");
 309                     }
 310                 }
 311                 @Override
 312                 public Object reached() {
 313                     return (testedControl.as(Parent.class, Node.class).lookup(Node.class, new ByID(id)).size() > 0)
 314                            ? 42 : null;
 315                     }
 316             });
 317 
 318         }
 319     }
 320 
 321     protected String getCellText(final Wrap<? extends Labeled> wrap) {
 322         return new GetAction<String>() {
 323             @Override
 324             public void run(Object... parameters) throws Exception {
 325                 setResult(((Labeled)wrap.getControl()).getText());
 326             }
 327         }.dispatch(testedControl.getEnvironment());
 328     }
 329 
 330     protected void checkPopup() throws Exception {
 331         Lookup<Scene> lookup = Root.ROOT.lookup(new ByWindowType(PopupWindow.class))
 332                                          .lookup(Scene.class);
 333         if (lookup.size() != 1) {
 334             throw new Exception("Popup is expected to appear.");
 335         }
 336     }
 337 
 338     /*
 339      * Doesn't take nested columns into consideration.
 340      */
 341     protected Collection<TableColumnBase> getTopLevelColumns() {
 342         return new GetAction<Collection<TableColumnBase>>() {
 343 
 344             @Override
 345             public void run(Object... parameters) throws Exception {
 346                 Collection<TableColumnBase> cols;
 347                 Control control = testedControl.getControl();
 348 
 349                 if (isTableTests) {
 350                     cols = ((TableView) control).getColumns();
 351                 } else {
 352                     cols = ((TreeTableView) control).getColumns();
 353                 }
 354                 setResult(cols);
 355             }
 356         }.dispatch(testedControl.getEnvironment());
 357     }
 358 
 359     protected void setShowRoot(final boolean value) {
 360         if (!isTableTests) {
 361             new GetAction<Object>() {
 362 
 363                 @Override
 364                 public void run(Object... os) throws Exception {
 365                     ((TreeTableView) testedControl.getControl()).setShowRoot(value);
 366                 }
 367             }.dispatch(testedControl.getEnvironment());
 368 
 369             try {
 370                 TimeUnit.MILLISECONDS.sleep(1000);
 371             } catch (Exception e) {
 372             }
 373         }
 374     }
 375 
 376     protected void sortColumnsByName(final boolean isAscending) {
 377         new GetAction<Object>() {
 378             private Comparator<TableColumnBase> comparator = new Comparator<TableColumnBase>() {
 379                 public int compare(TableColumnBase o1, TableColumnBase o2) {
 380                     int result = o1.getText().compareTo(o2.getText());
 381                     return isAscending ? result : -result;
 382                 }
 383             };
 384 
 385             @Override
 386             public void run(Object... os) throws Exception {
 387                 if (isTableTests) {
 388                     FXCollections.sort(((TableView) testedControl.getControl()).getColumns(), comparator);
 389                 } else {
 390                     FXCollections.sort(((TreeTableView) testedControl.getControl()).getColumns(), comparator);
 391                 }
 392             }
 393         }.dispatch(testedControl.getEnvironment());
 394 
 395         try {
 396             TimeUnit.MILLISECONDS.sleep(1000);
 397         } catch (Exception e) {
 398         }
 399     }
 400 }