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.utils.ptables;
  26 
  27 import java.lang.reflect.Method;
  28 import java.util.ArrayList;
  29 import java.util.Arrays;
  30 import java.util.Comparator;
  31 import java.util.List;
  32 import javafx.beans.property.*;
  33 import javafx.collections.FXCollections;
  34 import javafx.collections.ObservableList;
  35 import javafx.scene.Cursor;
  36 import javafx.scene.ImageCursor;
  37 import javafx.scene.Node;
  38 import javafx.scene.control.ContextMenu;
  39 import javafx.scene.control.Label;
  40 import javafx.scene.control.MenuItem;
  41 import javafx.scene.control.TableColumn;
  42 import javafx.scene.control.Tooltip;
  43 import javafx.scene.control.test.utils.ComponentsFactory;
  44 import javafx.scene.image.Image;
  45 import javafx.scene.paint.Color;
  46 import javafx.scene.shape.Circle;
  47 import javafx.scene.shape.PolygonBuilder;
  48 import javafx.scene.shape.Rectangle;
  49 import javafx.scene.text.Font;
  50 import javafx.scene.text.Text;
  51 import java.time.chrono.Chronology;
  52 
  53 /**
  54  * @author Alexander Kirov
  55  *
  56  * NOTION: this class should be instantiated on JavaFX thread.
  57  */
  58 public class PropertyTablesFactory {
  59 
  60     static ObservableList<String> excludeList = FXCollections.observableArrayList();
  61 
  62     static {
  63         /*
  64          * These properties are from Node so they are not needed for control
  65          * testing. They can anyway be added manually to the accordiong
  66          * PropertiesTable.
  67          */
  68         excludeList.addAll("id", "blendMode", "cache", "style", "clip", "cacheHint", "depthTest",
  69                 "pickOnBounds", "managed", "layoutX", "layoutY", "layoutZ", "scene", "needsLayout",
  70                 "translateX", "translateY", "translateZ", "scaleX", "scaleY", "scaleZ",
  71                 "minWidth", "maxWidth", "minHeight", "maxHeight", "impl_showMnemonics");
  72     }
  73 
  74     private static boolean propertyIsExculded(String propertyName) {
  75         return excludeList.contains(propertyName);
  76     }
  77 
  78     public static void explorePropertiesList(Object control, PropertiesTable tb) {
  79         Method[] all_methods = control.getClass().getMethods();
  80         for (Method method : all_methods) {
  81             try {
  82                 if (method.getName().endsWith("Property")) {
  83                     String propertyName = method.getName().substring(0, method.getName().indexOf("Property"));
  84                     if (!propertyIsExculded(propertyName)) {
  85                         Class storedObjectClass = null;
  86 
  87                         try {
  88                             Method getter = control.getClass().getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1, propertyName.length()));
  89                             storedObjectClass = getter.getReturnType();
  90                         } catch (Exception ex) {
  91                         }
  92 
  93                         if (method.getReturnType() == ObjectProperty.class) {
  94                             if ((method.getReturnType().getGenericInterfaces().length > 0)) {
  95                                 if (storedObjectClass == Tooltip.class) {
  96                                     provideTooltipObjectEnumPropertyLine((ObjectProperty) method.invoke(control), tb, control);
  97                                 }
  98 
  99                                 if (storedObjectClass == Comparator.class) {
 100                                     provideComparatorPropertyLine((ObjectProperty) method.invoke(control), tb, control);
 101                                 }
 102 
 103                                 if (storedObjectClass == ContextMenu.class) {
 104                                     provideContextMenuObjectEnumPropertyLine((ObjectProperty) method.invoke(control), tb, control);
 105                                 }
 106 
 107                                 if (storedObjectClass == Cursor.class) {
 108                                     provideCursorObjectEnumPropertyLine((ObjectProperty) method.invoke(control), tb, control);
 109                                 }
 110 
 111                                 if (storedObjectClass == Font.class) {
 112                                     provideFontObjectEnumPropertyLine((ObjectProperty) method.invoke(control), tb, control);
 113                                 }
 114 
 115                                 if (storedObjectClass == Node.class) {
 116                                     provideCustomNodeObjectEnumPropertyLine((ObjectProperty) method.invoke(control), tb, control);
 117                                 }
 118 
 119                                 if (storedObjectClass == Chronology.class) {
 120                                     provideChronologyObjectEnumPropertyLine((ObjectProperty) method.invoke(control), tb, control);
 121                                 }
 122 
 123                                 if (!(storedObjectClass == null) && storedObjectClass.isEnum()) {
 124                                     tb.addObjectEnumPropertyLine((ObjectProperty) method.invoke(control), Arrays.asList(storedObjectClass.getEnumConstants()), control);
 125                                 }
 126                             }
 127                         }
 128                         if (method.getReturnType() == DoubleProperty.class) {
 129                             PropertiesConstraints.NumericConstraints constr = PropertiesConstraints.getNumericConstraint(propertyName);
 130                             tb.addDoublePropertyLine((DoubleProperty) method.invoke(control), constr.min, constr.max, constr.default_value, control);
 131                         }
 132                         if (method.getReturnType() == IntegerProperty.class) {
 133                             PropertiesConstraints.NumericConstraints constr = PropertiesConstraints.getNumericConstraint(propertyName);
 134                             tb.addIntegerPropertyLine((IntegerProperty) method.invoke(control), (int) Math.round(constr.min), (int) Math.round(constr.max), (int) Math.round(constr.default_value));
 135                         }
 136                         if (method.getReturnType() == StringProperty.class) {
 137                             tb.addStringLine((Property) method.invoke(control), "Some text");
 138                         }
 139                         if (method.getReturnType() == BooleanProperty.class) {
 140                             tb.addBooleanPropertyLine((Property) method.invoke(control), control);
 141                         }
 142 
 143                         try {
 144                             Object ob = method.invoke(control);
 145                             if (ob.getClass().getName().contains("ReadOnly")) {
 146                                 tb.addSimpleListener((ReadOnlyProperty) ob, control);
 147                             }
 148                         } catch (Exception ex) {
 149                         }
 150                     }
 151                 }
 152             } catch (Throwable ex) {
 153                 System.err.println("Was an error, on invoke the method : " + method + ", parsing control " + control);
 154                 ex.printStackTrace(System.out);
 155             }
 156         }
 157     }
 158 
 159     public static void provideFontObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 160         List possibleFonts = new ArrayList();
 161         possibleFonts.add(null);
 162         possibleFonts.add(new Font(20));
 163         possibleFonts.add(new Font("ArialW7", 15));
 164         possibleFonts.add(new Font("Verdana", 10));
 165         tb.addObjectEnumPropertyLine(property, possibleFonts, owningObject);
 166     }
 167 
 168     public static Tooltip provideTooltipObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 169         Tooltip tp = new Tooltip("Tooltip");
 170         List possibleTooltips = new ArrayList();
 171         possibleTooltips.add(null);
 172         possibleTooltips.add(tp);
 173         tb.addObjectEnumPropertyLine(property, possibleTooltips, owningObject);
 174         return tp;
 175     }
 176 
 177     public static ContextMenu provideContextMenuObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 178         ContextMenu cm = new ContextMenu();
 179         cm.getItems().add(new MenuItem("SomeItem"));
 180         List possibleMenus = new ArrayList();
 181         possibleMenus.add(null);
 182         possibleMenus.add(cm);
 183         tb.addObjectEnumPropertyLine(property, possibleMenus, owningObject);
 184         return cm;
 185     }
 186 
 187     public static void provideCustomNodeObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 188         List possibleNodes = new ArrayList();
 189         possibleNodes.add(null);
 190         possibleNodes.add(new Text("This is custom node"));
 191         possibleNodes.add(new Label("Label text", new Text("Label node")));
 192         possibleNodes.add(new Rectangle(0, 0, 10, 10));
 193         possibleNodes.add(ComponentsFactory.createCustomContent(25, 25));
 194         possibleNodes.add(new Circle(6.75, Color.RED));
 195         possibleNodes.add(PolygonBuilder.create().fill(Color.GREEN).points(new Double[]{
 196                     0.0, 7.0,
 197                     5.0, 20.0,
 198                     15.0, 20.0,
 199                     20.0, 7.0,
 200                     10.0, 0.0,}).build());
 201         tb.addObjectEnumPropertyLine(property, possibleNodes, owningObject);
 202     }
 203 
 204 //    public static void provideChronologyObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 205 //        List possibleChronologies = new ArrayList();
 206 //        possibleChronologies.add(null);
 207 //        possibleChronologies.addAll(java.time.chrono.Chronology.getAvailableChronologies());
 208 //        tb.addObjectEnumPropertyLine(property, possibleChronologies, owningObject);
 209 //    }
 210 
 211     public static Cursor provideCursorObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 212         ImageCursor c1 = new ImageCursor(new Image("https://svn.java.net/svn/fxtest-golden~images-svn/ControlsTests/JavaProgBarInd80x80.gif"));
 213         List possibleTooltips = new ArrayList();
 214         possibleTooltips.add(null);
 215         possibleTooltips.add(c1);
 216         tb.addObjectEnumPropertyLine(property, possibleTooltips, owningObject);
 217         return c1;
 218     }
 219 
 220     public static void provideComparatorPropertyLine(ObjectProperty property, PropertiesTable tb, Object owningObject) {
 221         List possibleComparators = new ArrayList();
 222         possibleComparators.add(null);
 223         possibleComparators.add(new CustomReversedComparator());
 224         possibleComparators.add(TableColumn.DEFAULT_COMPARATOR);
 225         tb.addObjectEnumPropertyLine(property, possibleComparators, owningObject);
 226     }
 227 
 228     private static void provideChronologyObjectEnumPropertyLine(ObjectProperty property, PropertiesTable tb, Object control) {
 229         ArrayList<Chronology> values = new ArrayList<Chronology>();
 230         values.add(null);
 231         values.add(Chronology.of("ISO"));
 232         values.add(Chronology.of("Minguo"));
 233         values.add(Chronology.of("ThaiBuddhist"));
 234         values.add(Chronology.of("Japanese"));
 235         values.add(Chronology.of("Hijrah-umalqura"));
 236 
 237         tb.addObjectEnumPropertyLine(property, values, control);
 238     }
 239 
 240     public static class CustomReversedComparator implements Comparator {
 241         //This is reversed comparator.
 242 
 243         public static final String comparatorName = "Custom reversed comparator";
 244 
 245         public int compare(Object t1, Object t2) {
 246             return -t1.toString().compareTo(t2.toString());
 247         }
 248 
 249         @Override
 250         public String toString() {
 251             return comparatorName;
 252         }
 253     }
 254 }