Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.beans.property; 027 028import javafx.beans.InvalidationListener; 029import javafx.beans.Observable; 030import javafx.beans.binding.FloatBinding; 031import javafx.beans.value.ChangeListener; 032import javafx.beans.value.ObservableValue; 033 034import com.sun.javafx.binding.ExpressionHelper; 035import javafx.beans.value.ObservableFloatValue; 036import javafx.beans.value.ObservableNumberValue; 037 038/** 039 * The class {@code FloatPropertyBase} is the base class for a property wrapping 040 * a {@code float} value. 041 * 042 * It provides all the functionality required for a property except for the 043 * {@link #getBean()} and {@link #getName()} methods, which must be implemented 044 * by extending classes. 045 * 046 * @see FloatProperty 047 * 048 * 049 */ 050public abstract class FloatPropertyBase extends FloatProperty { 051 052 private float value; 053 private ObservableFloatValue observable = null;; 054 private InvalidationListener listener = null; 055 private boolean valid = true; 056 private ExpressionHelper<Number> helper = null; 057 058 /** 059 * The constructor of the {@code FloatPropertyBase}. 060 */ 061 public FloatPropertyBase() { 062 } 063 064 /** 065 * The constructor of the {@code FloatPropertyBase}. 066 * 067 * @param initialValue 068 * the initial value of the wrapped value 069 */ 070 public FloatPropertyBase(float initialValue) { 071 this.value = initialValue; 072 } 073 074 @Override 075 public void addListener(InvalidationListener listener) { 076 helper = ExpressionHelper.addListener(helper, this, listener); 077 } 078 079 @Override 080 public void removeListener(InvalidationListener listener) { 081 helper = ExpressionHelper.removeListener(helper, listener); 082 } 083 084 @Override 085 public void addListener(ChangeListener<? super Number> listener) { 086 helper = ExpressionHelper.addListener(helper, this, listener); 087 } 088 089 @Override 090 public void removeListener(ChangeListener<? super Number> listener) { 091 helper = ExpressionHelper.removeListener(helper, listener); 092 } 093 094 /** 095 * Sends notifications to all attached 096 * {@link javafx.beans.InvalidationListener InvalidationListeners} and 097 * {@link javafx.beans.value.ChangeListener ChangeListeners}. 098 * 099 * This method is called when the value is changed, either manually by 100 * calling {@link #set(float)} or in case of a bound property, if the 101 * binding becomes invalid. 102 */ 103 protected void fireValueChangedEvent() { 104 ExpressionHelper.fireValueChangedEvent(helper); 105 } 106 107 private void markInvalid() { 108 if (valid) { 109 valid = false; 110 invalidated(); 111 fireValueChangedEvent(); 112 } 113 } 114 115 /** 116 * The method {@code invalidated()} can be overridden to receive 117 * invalidation notifications. This is the preferred option in 118 * {@code Objects} defining the property, because it requires less memory. 119 * 120 * The default implementation is empty. 121 */ 122 protected void invalidated() { 123 } 124 125 /** 126 * {@inheritDoc} 127 */ 128 @Override 129 public float get() { 130 valid = true; 131 return observable == null ? value : observable.get(); 132 } 133 134 /** 135 * {@inheritDoc} 136 */ 137 @Override 138 public void set(float newValue) { 139 if (isBound()) { 140 throw new java.lang.RuntimeException("A bound value cannot be set."); 141 } 142 if (value != newValue) { 143 value = newValue; 144 markInvalid(); 145 } 146 } 147 148 /** 149 * {@inheritDoc} 150 */ 151 @Override 152 public boolean isBound() { 153 return observable != null; 154 } 155 156 /** 157 * {@inheritDoc} 158 */ 159 @Override 160 public void bind(final ObservableValue<? extends Number> rawObservable) { 161 if (rawObservable == null) { 162 throw new NullPointerException("Cannot bind to null"); 163 } 164 165 ObservableFloatValue newObservable; 166 if (rawObservable instanceof ObservableFloatValue) { 167 newObservable = (ObservableFloatValue)rawObservable; 168 } else if (rawObservable instanceof ObservableNumberValue) { 169 final ObservableNumberValue numberValue = (ObservableNumberValue)rawObservable; 170 newObservable = new FloatBinding() { 171 { 172 super.bind(rawObservable); 173 } 174 175 @Override 176 protected float computeValue() { 177 return numberValue.floatValue(); 178 } 179 }; 180 } else { 181 newObservable = new FloatBinding() { 182 { 183 super.bind(rawObservable); 184 } 185 186 @Override 187 protected float computeValue() { 188 final Number value = rawObservable.getValue(); 189 return (value == null)? 0.0f : value.floatValue(); 190 } 191 }; 192 } 193 194 195 if (!newObservable.equals(observable)) { 196 unbind(); 197 observable = newObservable; 198 if (listener == null) { 199 listener = new Listener(); 200 } 201 observable.addListener(listener); 202 markInvalid(); 203 } 204 } 205 206 /** 207 * {@inheritDoc} 208 */ 209 @Override 210 public void unbind() { 211 if (observable != null) { 212 value = observable.get(); 213 observable.removeListener(listener); 214 observable = null; 215 } 216 } 217 218 /** 219 * Returns a string representation of this {@code FloatPropertyBase} object. 220 * @return a string representation of this {@code FloatPropertyBase} object. 221 */ 222 @Override 223 public String toString() { 224 final Object bean = getBean(); 225 final String name = getName(); 226 final StringBuilder result = new StringBuilder("FloatProperty ["); 227 if (bean != null) { 228 result.append("bean: ").append(bean).append(", "); 229 } 230 if ((name != null) && (!name.equals(""))) { 231 result.append("name: ").append(name).append(", "); 232 } 233 if (isBound()) { 234 result.append("bound, "); 235 if (valid) { 236 result.append("value: ").append(get()); 237 } else { 238 result.append("invalid"); 239 } 240 } else { 241 result.append("value: ").append(get()); 242 } 243 result.append("]"); 244 return result.toString(); 245 } 246 247 private class Listener implements InvalidationListener { 248 @Override 249 public void invalidated(Observable valueModel) { 250 markInvalid(); 251 } 252 } 253}