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.LongBinding; 031import javafx.beans.value.ChangeListener; 032import javafx.beans.value.ObservableValue; 033 034import com.sun.javafx.binding.ExpressionHelper; 035import javafx.beans.value.ObservableLongValue; 036import javafx.beans.value.ObservableNumberValue; 037 038/** 039 * The class {@code LongPropertyBase} is the base class for a property wrapping 040 * a {@code long} 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 LongProperty 047 * 048 * 049 */ 050public abstract class LongPropertyBase extends LongProperty { 051 052 private long value; 053 private ObservableLongValue 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 LongPropertyBase}. 060 */ 061 public LongPropertyBase() { 062 } 063 064 /** 065 * The constructor of the {@code LongPropertyBase}. 066 * 067 * @param initialValue 068 * the initial value of the wrapped value 069 */ 070 public LongPropertyBase(long 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(long)} 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 long get() { 130 valid = true; 131 return observable == null ? value : observable.get(); 132 } 133 134 /** 135 * {@inheritDoc} 136 */ 137 @Override 138 public void set(long 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 ObservableLongValue newObservable; 166 if (rawObservable instanceof ObservableLongValue) { 167 newObservable = (ObservableLongValue)rawObservable; 168 } else if (rawObservable instanceof ObservableNumberValue) { 169 final ObservableNumberValue numberValue = (ObservableNumberValue)rawObservable; 170 newObservable = new LongBinding() { 171 { 172 super.bind(rawObservable); 173 } 174 175 @Override 176 protected long computeValue() { 177 return numberValue.longValue(); 178 } 179 }; 180 } else { 181 newObservable = new LongBinding() { 182 { 183 super.bind(rawObservable); 184 } 185 186 @Override 187 protected long computeValue() { 188 final Number value = rawObservable.getValue(); 189 return (value == null)? 0L : value.longValue(); 190 } 191 }; 192 } 193 194 if (!newObservable.equals(observable)) { 195 unbind(); 196 observable = newObservable; 197 if (listener == null) { 198 listener = new Listener(); 199 } 200 observable.addListener(listener); 201 markInvalid(); 202 } 203 } 204 205 /** 206 * {@inheritDoc} 207 */ 208 @Override 209 public void unbind() { 210 if (observable != null) { 211 value = observable.get(); 212 observable.removeListener(listener); 213 observable = null; 214 } 215 } 216 217 /** 218 * Returns a string representation of this {@code LongPropertyBase} object. 219 * @return a string representation of this {@code LongPropertyBase} object. 220 */ 221 @Override 222 public String toString() { 223 final Object bean = getBean(); 224 final String name = getName(); 225 final StringBuilder result = new StringBuilder("LongProperty ["); 226 if (bean != null) { 227 result.append("bean: ").append(bean).append(", "); 228 } 229 if ((name != null) && (!name.equals(""))) { 230 result.append("name: ").append(name).append(", "); 231 } 232 if (isBound()) { 233 result.append("bound, "); 234 if (valid) { 235 result.append("value: ").append(get()); 236 } else { 237 result.append("invalid"); 238 } 239 } else { 240 result.append("value: ").append(get()); 241 } 242 result.append("]"); 243 return result.toString(); 244 } 245 246 private class Listener implements InvalidationListener { 247 @Override 248 public void invalidated(Observable valueModel) { 249 markInvalid(); 250 } 251 } 252}