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