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 javafx.beans.property.Property;
  29 import javafx.event.ActionEvent;
  30 import javafx.event.EventHandler;
  31 import javafx.scene.control.Button;
  32 import javafx.scene.control.Control;
  33 import javafx.scene.control.Label;
  34 import static javafx.scene.control.test.utils.ptables.StaticLogger.*;
  35 import javafx.scene.layout.HBox;
  36 
  37 /**
  38  * @author Alexander Kirov
  39  *
  40  * Partial implementation of mechanism of binding and unbinding, setters
  41  * implementing, and this functionality aggregating.
  42  */
  43 public abstract class AbstractPropertyValueSetter<ValueType> extends HBox implements AbstractPropertySetter<ValueType> {
  44 
  45     public final static String BIND_BUTTON_SUFFIX = "_BIND_BUTTON_ID";
  46     public final static String BIDIR_PREFIX = "BIDIR_";
  47     public final static String UNIDIR_PREFIX = "UNIDIR_";
  48     public final static String SET_PREFIX = "SETTER_";
  49     public final static String CONTROLLER_SUFFIX = "_CONTROLLER_ID";
  50     protected Property leadingProperty;
  51     protected Property listeningProperty;
  52     protected AbstractBindingSwitcher binding;
  53     protected Control leadingControl;
  54     protected Object initialValue1;
  55     protected Object initialValue2;
  56     protected Object initialValue3;
  57     protected PropertyValueType propertyValueType;
  58     private BindingType btype;
  59     private EventHandler<ActionEvent> setAction;
  60 
  61     protected void bindComponent(final BindingType btype, final Object testedControl) {
  62         this.btype = btype;
  63         String bindButtonId = ((btype == BindingType.UNIDIRECTIONAL) ? UNIDIR_PREFIX : BIDIR_PREFIX) + listeningProperty.getName().toUpperCase() + BIND_BUTTON_SUFFIX;
  64         setStyle("-fx-border-color : black;");
  65         setSpacing(3);
  66 
  67         binding = new ToggleBindingSwitcher(leadingProperty, listeningProperty, btype);
  68         binding.getVisualRepresentation().setId(bindButtonId);
  69 
  70         String labelDescription = btype.equals(BindingType.UNIDIRECTIONAL) ? "UNIDIR" : "BIDIR";
  71         getChildren().addAll(new Label(labelDescription.toUpperCase().substring(0, Math.min(15, labelDescription.length()) - 1)), leadingControl, binding.getVisualRepresentation());
  72 
  73         if (btype == BindingType.UNIDIRECTIONAL) {
  74             Button setButton = new Button("set");
  75             setButton.setMinWidth(38);
  76             setButton.setId(SET_PREFIX + listeningProperty.getName().toUpperCase());
  77             setAction = new EventHandler<ActionEvent>() {
  78                 public void handle(ActionEvent t) {
  79                     //bindingTB.setSelected(false);I think, that is not obligative.
  80                     //But otherwise, exception will be thrown each time, when unidirectional binding is switched on.
  81                     Method setter;
  82                     try {
  83                         Object value = listeningProperty.getValue();
  84 
  85                         Class returnClass;
  86 
  87 
  88                         if (value instanceof Boolean) {
  89                             returnClass = boolean.class;
  90                         } else {
  91                             returnClass = testedControl.getClass().getMethod("get" + listeningProperty.getName().substring(0, 1).toUpperCase() + listeningProperty.getName().substring(1, listeningProperty.getName().length())).getReturnType();
  92                         }
  93 
  94                         Object argument = leadingProperty.getValue();
  95                         if (value instanceof Integer) {
  96                             argument = (int) Math.round((Double) argument);
  97                         }
  98 
  99                         setter = testedControl.getClass().getMethod("set" + listeningProperty.getName().substring(0, 1).toUpperCase() + listeningProperty.getName().substring(1, listeningProperty.getName().length()), returnClass);
 100                         setter.invoke(testedControl, argument);
 101                     } catch (Throwable ex) {
 102                         log(ex);
 103                     }
 104                 }
 105             };
 106             setButton.setOnAction(setAction);
 107             getChildren().add(setButton);
 108         }
 109     }
 110 
 111     public static String createId(Property property, BindingType btype) {
 112         try {
 113             return btype.getPrefix() + property.getName().toUpperCase() + CONTROLLER_SUFFIX;
 114         } catch (Throwable ex) {
 115             log(ex);
 116         }
 117         return null;
 118     }
 119 
 120     public void setBindingState(Boolean newState) {
 121         binding.setBindingState(newState);
 122     }
 123 
 124     public Boolean getBindingState() {
 125         return binding.getBindingState();
 126     }
 127 
 128     public PropertyValueType getPropertyValueType() {
 129         return propertyValueType;
 130     }
 131 
 132     public void setValueThroughtBidirectionalBinding(ValueType value) {
 133         if (btype.equals(BindingType.UNIDIRECTIONAL)) {
 134             throw new IllegalStateException("Bidirectional setting is not applicable with unirectional binding option.");
 135         }
 136         try {
 137             leadingProperty.setValue(value);
 138         } catch (Throwable ex) {
 139             log(ex);
 140         }
 141     }
 142 
 143     public void setValueThroughtUnidirectionalBinding(ValueType value) {
 144         if (btype.equals(BindingType.BIDIRECTIONAL)) {
 145             throw new IllegalStateException("Unidirectional setting is not applicable with bidirectional binding option.");
 146         }
 147         try {
 148             leadingProperty.setValue(value);
 149         } catch (Throwable ex) {
 150             log(ex);
 151         }
 152     }
 153 
 154     public void setValueThroughtSetter(ValueType value) {
 155         if (btype.equals(BindingType.BIDIRECTIONAL)) {
 156             throw new IllegalStateException("Setter setting is not applicable with bidirectional binding option.");
 157         }
 158         if (setAction == null) {
 159             throw new IllegalArgumentException("Set action cannot be done.");
 160         }
 161         try {
 162             leadingProperty.setValue(value);
 163             setAction.handle(null);
 164         } catch (Throwable ex) {
 165             log(ex);
 166         }
 167     }
 168 
 169     public static enum BindingType {
 170 
 171         UNIDIRECTIONAL, BIDIRECTIONAL;
 172 
 173         public String getPrefix() {
 174             if (this.equals(BindingType.BIDIRECTIONAL)) {
 175                 return "BIDIR_";
 176             }
 177             if (this.equals(BindingType.UNIDIRECTIONAL)) {
 178                 return "UNIDIR_";
 179             }
 180             return null;
 181         }
 182     };
 183 }