1 /*
   2  * Copyright (c) 2011, 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 
  26 package javafx.beans.property;
  27 
  28 import com.sun.javafx.binding.BidirectionalBinding;
  29 import com.sun.javafx.binding.ExpressionHelper;
  30 import javafx.beans.binding.Bindings;
  31 import javafx.beans.value.ObservableValue;
  32 import javafx.beans.value.WritableDoubleValue;
  33 import com.sun.javafx.binding.Logging;
  34 import javafx.beans.InvalidationListener;
  35 import javafx.beans.Observable;
  36 import javafx.beans.WeakInvalidationListener;
  37 import javafx.beans.value.ChangeListener;
  38 import javafx.beans.value.ObservableDoubleValue;
  39 
  40 /**
  41  * This class defines a {@link Property} wrapping a {@code double} value.
  42  * <p>
  43  * The value of a {@code DoubleProperty} can be get and set with {@link #get()},
  44  * {@link #getValue()}, {@link #set(double)}, and {@link #setValue(Number)}.
  45  * <p>
  46  * A property can be bound and unbound unidirectional with
  47  * {@link #bind(ObservableValue)} and {@link #unbind()}. Bidirectional bindings
  48  * can be created and removed with {@link #bindBidirectional(Property)} and
  49  * {@link #unbindBidirectional(Property)}.
  50  * <p>
  51  * The context of a {@code DoubleProperty} can be read with {@link #getBean()}
  52  * and {@link #getName()}.
  53  * <p>
  54  * Note: setting or binding this property to a null value will set the property to "0.0". See {@link #setValue(java.lang.Number) }.
  55  *
  56  * @see javafx.beans.value.ObservableDoubleValue
  57  * @see javafx.beans.value.WritableDoubleValue
  58  * @see ReadOnlyDoubleProperty
  59  * @see Property
  60  *
  61  * @since JavaFX 2.0
  62  */
  63 public abstract class DoubleProperty extends ReadOnlyDoubleProperty implements
  64         Property<Number>, WritableDoubleValue {
  65 
  66     /**
  67      * {@inheritDoc}
  68      */
  69     @Override
  70     public void setValue(Number v) {
  71         if (v == null) {
  72             Logging.getLogger().fine("Attempt to set double property to null, using default value instead.", new NullPointerException());
  73             set(0.0);
  74         } else {
  75             set(v.doubleValue());
  76         }
  77     }
  78 
  79     /**
  80      * {@inheritDoc}
  81      */
  82     @Override
  83     public void bindBidirectional(Property<Number> other) {
  84         Bindings.bindBidirectional(this, other);
  85     }
  86 
  87     /**
  88      * {@inheritDoc}
  89      */
  90     @Override
  91     public void unbindBidirectional(Property<Number> other) {
  92         Bindings.unbindBidirectional(this, other);
  93     }
  94 
  95     /**
  96      * Returns a string representation of this {@code DoubleProperty} object.
  97      * @return a string representation of this {@code DoubleProperty} object.
  98      */
  99     @Override
 100     public String toString() {
 101         final Object bean = getBean();
 102         final String name = getName();
 103         final StringBuilder result = new StringBuilder(
 104                 "DoubleProperty [");
 105         if (bean != null) {
 106             result.append("bean: ").append(bean).append(", ");
 107         }
 108         if ((name != null) && (!name.equals(""))) {
 109             result.append("name: ").append(name).append(", ");
 110         }
 111         result.append("value: ").append(get()).append("]");
 112         return result.toString();
 113     }
 114 
 115     /**
 116      * Returns a {@code DoubleProperty} that wraps a
 117      * {@link javafx.beans.property.Property} and is
 118      * bidirectionally bound to it.
 119      * Changing this property will result in a change of the original property.
 120      *
 121      * <p>
 122      * This is very useful when bidirectionally binding an ObjectProperty<Double> and
 123      * a DoubleProperty.
 124      *
 125      * <blockquote><pre>
 126      *   DoubleProperty doubleProperty = new SimpleDoubleProperty(1.0);
 127      *   ObjectProperty&lt;Double&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2.0);
 128      *
 129      *   // Need to keep the reference as bidirectional binding uses weak references
 130      *   DoubleProperty objectAsDouble = DoubleProperty.doubleProperty(objectProperty);
 131      *
 132      *   doubleProperty.bindBidirectional(objectAsDouble);
 133      *
 134      * </pre></blockquote>
 135      *
 136      * Another approach is to convert the DoubleProperty to ObjectProperty using
 137      * {@link #asObject()} method.
 138      * <p>
 139      * Note: null values in the source property will be interpreted as 0.0
 140      *
 141      * @param property
 142      *            The source {@code Property}
 143      * @return A {@code DoubleProperty} that wraps the
 144      *         {@code Property}
 145      * @throws NullPointerException
 146      *             if {@code property} is {@code null}
 147      * @see #asObject()
 148      * @since JavaFX 8.0
 149      */
 150     public static DoubleProperty doubleProperty(final Property<Double> property) {
 151         if (property == null) {
 152             throw new NullPointerException("Property cannot be null");
 153         }
 154         return new DoublePropertyBase() {
 155             {
 156                 BidirectionalBinding.bindNumber(this, property);
 157             }
 158 
 159             @Override
 160             public Object getBean() {
 161                 return null; // Virtual property, no bean
 162             }
 163 
 164             @Override
 165             public String getName() {
 166                 return property.getName();
 167             }
 168 
 169             @Override
 170             protected void finalize() throws Throwable {
 171                 try {
 172                     BidirectionalBinding.unbindNumber(property, this);
 173                 } finally {
 174                     super.finalize();
 175                 }
 176             }
 177         };
 178     }
 179 
 180     /**
 181      * Creates an {@link javafx.beans.property.ObjectProperty}
 182      * that bidirectionally bound to this {@code DoubleProperty}. If the
 183      * value of this {@code DoubleProperty} changes, the value of the
 184      * {@code ObjectProperty} will be updated automatically and vice-versa.
 185      *
 186      * <p>
 187      * Can be used for binding an ObjectProperty to DoubleProperty.
 188      *
 189      * <blockquote><pre>
 190      *   DoubleProperty doubleProperty = new SimpleDoubleProperty(1.0);
 191      *   ObjectProperty&lt;Double&gt; objectProperty = new SimpleObjectProperty&lt;&gt;(2.0);
 192      *
 193      *   objectProperty.bind(doubleProperty.asObject());
 194      * </pre></blockquote>
 195      *
 196      * @return the new {@code ObjectProperty}
 197      * @since JavaFX 8.0
 198      */
 199     @Override
 200     public ObjectProperty<Double> asObject() {
 201         return new ObjectPropertyBase<Double> () {
 202 
 203             {
 204                 BidirectionalBinding.bindNumber(this, DoubleProperty.this);
 205             }
 206 
 207             @Override
 208             public Object getBean() {
 209                 return null; // Virtual property, does not exist on a bean
 210             }
 211 
 212             @Override
 213             public String getName() {
 214                 return DoubleProperty.this.getName();
 215             }
 216 
 217             @Override
 218             protected void finalize() throws Throwable {
 219                 try {
 220                     BidirectionalBinding.unbindNumber(this, DoubleProperty.this);
 221                 } finally {
 222                     super.finalize();
 223                 }
 224             }
 225 
 226         };
 227     }
 228 
 229 
 230 }