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