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.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.Collection; 30 import java.util.HashMap; 31 import java.util.List; 32 import javafx.beans.property.DoubleProperty; 33 import javafx.beans.property.IntegerProperty; 34 import javafx.beans.property.ObjectProperty; 35 import javafx.beans.property.Property; 36 import javafx.beans.property.ReadOnlyProperty; 37 import javafx.scene.Node; 38 import javafx.scene.layout.FlowPane; 39 import javafx.scene.layout.FlowPaneBuilder; 40 import javafx.scene.layout.VBox; 41 import static javafx.scene.control.test.utils.ptables.AbstractApplicationPropertiesRegystry.DEFAULT_DOMAIN_NAME; 42 43 /** 44 * @author Alexander Kirov 45 * 46 * This class provide functionality, which is used for creating scene component, 47 * which provide control over different tested control's (node's) properties. 48 * 49 * NOTION: this class should be instantiated on JavaFX thread. 50 * 51 * Use case: PropertiesTable axisProperties = new PropertiesTable(axis); 52 * axisProperties.addBooleanPropertyLine(axis.animatedProperty()); 53 * axisProperties.addDoublePropertyLine(axis.tickLengthProperty(), -5, 50, 5); 54 * axisProperties.addStringLine(axis.labelProperty(), "Label"); 55 * axisProperties.addSimpleListener(axis.hoverProperty(), axis); 56 * axisProperties.addObjectEnumPropertyLine(axis.sideProperty(), 57 * Arrays.asList(Side.values())); 58 * someContainer.getChildren().add(axisProperties.getContent());//To see it on 59 * scene. 60 * 61 * Automated PropertiesTable generation can be used: PropertiesTable tb = new 62 * PropertiesTable(testedSlider); Slider testedSlider = new Slider(); 63 * PropertyTablesFactory.explorePropertiesList(testedSlider, tb); 64 * SpecialTablePropertiesProvider.provideForControl(testedSlider, tb); Thus you 65 * can get control over all properties of slider. 66 * 67 * Also you can use functionality of counter. Counters can count increments: 68 * tb.addCounter(SET_ON_HIDING_COUNTER); testedComboBox.setOnHiding(new 69 * EventHandler<Event>() { public void handle(Event t) { 70 * tb.incrementCounter(SET_ON_HIDING_COUNTER); } }); Thus, you can count, how 71 * many times onHiding event happend. 72 * 73 * Look at class javafx.scene.control.test.util.UtilTestFunctions to see, which 74 * functionality of this PropertiesTable can be accessed from tests side (it 75 * contains different checkers, value setters, etc). 76 */ 77 public class PropertiesTable extends VBox implements AbstractPropertiesTable, Refreshable { 78 79 public final static String PROPERTIES_TABLE_SUFFIX_ID = "_PROPERTY_TABLE_ID"; 80 private final VBox linesVBox = new VBox(5); 81 private final FlowPane countersFlowPane = FlowPaneBuilder.create().vgap(5).hgap(5).build(); 82 private final FlowPane listenersFlowPane = FlowPaneBuilder.create().vgap(5).hgap(5).build(); 83 private final Object testedControl; 84 private String domainName; 85 /** 86 * Matches property name, on its controller. 87 */ 88 private HashMap<String, AbstractPropertyController> propertyControllers = new HashMap<String, AbstractPropertyController>(); 89 /** 90 * Matches counter name on its counter representation. 91 */ 92 private HashMap<String, AbstractEventsCounter> eventCounters = new HashMap<String, AbstractEventsCounter>(); 93 /** 94 * Matches property name on its listener (for read-only properties). 95 */ 96 private HashMap<String, AbstractPropertyValueListener> readonlyPropertyListeners = new HashMap<String, AbstractPropertyValueListener>(); 97 98 public PropertiesTable(Object testedControl) { 99 super(5); 100 this.domainName = DEFAULT_DOMAIN_NAME; 101 this.setId(DEFAULT_DOMAIN_NAME + PROPERTIES_TABLE_SUFFIX_ID); 102 getChildren().add(0, countersFlowPane); 103 getChildren().add(1, listenersFlowPane); 104 getChildren().add(2, linesVBox); 105 this.testedControl = testedControl; 106 } 107 108 public void refresh() { 109 for (AbstractPropertyController controller : propertyControllers.values()) { 110 controller.refresh(); 111 } 112 for (AbstractEventsCounter counter : eventCounters.values()) { 113 counter.refresh(); 114 } 115 for (AbstractPropertyValueListener listener : readonlyPropertyListeners.values()) { 116 listener.refresh(); 117 } 118 } 119 120 @Override 121 public void addBooleanPropertyLine(Property bindableProperty) { 122 AbstractPropertyController controller = new PropertyValueController(bindableProperty, testedControl); 123 propertyControllers.put(bindableProperty.getName().toUpperCase(), controller); 124 linesVBox.getChildren().add(controller.getVisualRepresentation()); 125 } 126 127 @Override 128 public void addBooleanPropertyLine(Property bindableProperty, Object owningObject) { 129 AbstractPropertyController controller = new PropertyValueController(bindableProperty, owningObject); 130 propertyControllers.put(bindableProperty.getName().toUpperCase(), controller); 131 linesVBox.getChildren().add(controller.getVisualRepresentation()); 132 } 133 134 @Override 135 public void addStringLine(Property bindableProperty, String initialText) { 136 addStringLine(bindableProperty, initialText, testedControl); 137 } 138 139 @Override 140 public void addStringLine(Property bindableProperty, String initialText, Object owningObject) { 141 AbstractPropertyController controller = new PropertyValueController(bindableProperty, owningObject, initialText); 142 propertyControllers.put(bindableProperty.getName().toUpperCase(), controller); 143 linesVBox.getChildren().add(controller.getVisualRepresentation()); 144 } 145 146 @Override 147 public void addDoublePropertyLine(final DoubleProperty bindableProperty, double min, double max, double initial) { 148 addDoublePropertyLine(bindableProperty, min, max, initial, testedControl); 149 } 150 151 @Override 152 public void addDoublePropertyLine(final DoubleProperty bindableProperty, double min, double max, double initial, Object owningObject) { 153 AbstractPropertyController controller = new PropertyValueController(bindableProperty, testedControl, min, initial, max); 154 propertyControllers.put(bindableProperty.getName().toUpperCase(), controller); 155 linesVBox.getChildren().add(controller.getVisualRepresentation()); 156 } 157 158 @Override 159 public void addIntegerPropertyLine(final IntegerProperty bindableProperty, int min, int max, int initial) { 160 AbstractPropertyController controller = new PropertyValueController(bindableProperty, testedControl, min, initial, max); 161 propertyControllers.put(bindableProperty.getName().toUpperCase(), controller); 162 linesVBox.getChildren().add(controller.getVisualRepresentation()); 163 } 164 165 @Override 166 public <T> void addObjectEnumPropertyLine(ObjectProperty<T> bindableProperty, List<T> valuesList) { 167 addObjectEnumPropertyLine(bindableProperty, valuesList, testedControl); 168 } 169 170 @Override 171 public <T> void addObjectEnumPropertyLine(ObjectProperty<T> bindableProperty, List<T> valuesList, Object owningObject) { 172 AbstractPropertyController controller = new PropertyValueController<T>(bindableProperty, owningObject, valuesList); 173 propertyControllers.put(bindableProperty.getName().toUpperCase(), controller); 174 linesVBox.getChildren().add(controller.getVisualRepresentation()); 175 } 176 177 @Override 178 public void addSimpleListener(ReadOnlyProperty<? extends Object> bindableProperty, Object owningObject) { 179 AbstractPropertyValueListener listener = new PropertyValueListener(bindableProperty, owningObject); 180 readonlyPropertyListeners.put(bindableProperty.getName().toUpperCase(), listener); 181 listenersFlowPane.getChildren().add(listener.getVisualRepresentation()); 182 } 183 184 @Override 185 public void addCounter(String counterName) { 186 AbstractEventsCounter counter = new TextFieldEventsCounter(counterName); 187 eventCounters.put(counterName.toUpperCase(), counter); 188 countersFlowPane.getChildren().add(counter.getVisualRepresentation()); 189 } 190 191 @Override 192 public void incrementCounter(String counterName) { 193 eventCounters.get(counterName.toUpperCase()).increment(); 194 } 195 196 public Collection<AbstractEventsCounter> getCounters() { 197 return eventCounters.values(); 198 } 199 200 public List<AbstractPropertyValueListener> getListeners() { 201 List<AbstractPropertyValueListener> temp = new ArrayList<AbstractPropertyValueListener>(Arrays.asList(readonlyPropertyListeners.values().toArray(new AbstractPropertyValueListener[0]))); 202 for (AbstractPropertyController controller : propertyControllers.values()) { 203 temp.add(controller.getListener()); 204 } 205 return temp; 206 } 207 208 public Node getVisualRepresentation() { 209 return this; 210 } 211 212 public String getDomainName() { 213 return this.domainName; 214 } 215 216 public void setDomainName(String domainName) { 217 this.domainName = domainName; 218 } 219 }