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.value.ChangeListener; 031import javafx.beans.value.ObservableValue; 032 033import com.sun.javafx.binding.ExpressionHelper; 034 035/** 036 * The class {@code ObjectPropertyBase} is the base class for a property 037 * wrapping an arbitrary {@code Object}. 038 * 039 * It provides all the functionality required for a property except for the 040 * {@link #getBean()} and {@link #getName()} methods, which must be implemented 041 * by extending classes. 042 * 043 * @see ObjectProperty 044 * 045 * 046 * @param <T> 047 * the type of the wrapped value 048 */ 049public abstract class ObjectPropertyBase<T> extends ObjectProperty<T> { 050 051 private T value; 052 private ObservableValue<? extends T> observable = null;; 053 private InvalidationListener listener = null; 054 private boolean valid = true; 055 private ExpressionHelper<T> helper = null; 056 057 /** 058 * The constructor of the {@code ObjectPropertyBase}. 059 */ 060 public ObjectPropertyBase() { 061 } 062 063 /** 064 * The constructor of the {@code ObjectPropertyBase}. 065 * 066 * @param initialValue 067 * the initial value of the wrapped {@code Object} 068 */ 069 public ObjectPropertyBase(T initialValue) { 070 this.value = initialValue; 071 } 072 073 @Override 074 public void addListener(InvalidationListener listener) { 075 helper = ExpressionHelper.addListener(helper, this, listener); 076 } 077 078 @Override 079 public void removeListener(InvalidationListener listener) { 080 helper = ExpressionHelper.removeListener(helper, listener); 081 } 082 083 @Override 084 public void addListener(ChangeListener<? super T> listener) { 085 helper = ExpressionHelper.addListener(helper, this, listener); 086 } 087 088 @Override 089 public void removeListener(ChangeListener<? super T> listener) { 090 helper = ExpressionHelper.removeListener(helper, listener); 091 } 092 093 /** 094 * Sends notifications to all attached 095 * {@link javafx.beans.InvalidationListener InvalidationListeners} and 096 * {@link javafx.beans.value.ChangeListener ChangeListeners}. 097 * 098 * This method is called when the value is changed, either manually by 099 * calling {@link #set} or in case of a bound property, if the 100 * binding becomes invalid. 101 */ 102 protected void fireValueChangedEvent() { 103 ExpressionHelper.fireValueChangedEvent(helper); 104 } 105 106 private void markInvalid() { 107 if (valid) { 108 valid = false; 109 invalidated(); 110 fireValueChangedEvent(); 111 } 112 } 113 114 /** 115 * The method {@code invalidated()} can be overridden to receive 116 * invalidation notifications. This is the preferred option in 117 * {@code Objects} defining the property, because it requires less memory. 118 * 119 * The default implementation is empty. 120 */ 121 protected void invalidated() { 122 } 123 124 /** 125 * {@inheritDoc} 126 */ 127 @Override 128 public T get() { 129 valid = true; 130 return observable == null ? value : observable.getValue(); 131 } 132 133 /** 134 * {@inheritDoc} 135 */ 136 @Override 137 public void set(T newValue) { 138 if (isBound()) { 139 throw new java.lang.RuntimeException("A bound value cannot be set."); 140 } 141 if (value != newValue) { 142 value = newValue; 143 markInvalid(); 144 } 145 } 146 147 /** 148 * {@inheritDoc} 149 */ 150 @Override 151 public boolean isBound() { 152 return observable != null; 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 @Override 159 public void bind(final ObservableValue<? extends T> newObservable) { 160 if (newObservable == null) { 161 throw new NullPointerException("Cannot bind to null"); 162 } 163 164 if (!newObservable.equals(this.observable)) { 165 unbind(); 166 observable = newObservable; 167 if (listener == null) { 168 listener = new Listener(); 169 } 170 observable.addListener(listener); 171 markInvalid(); 172 } 173 } 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override 179 public void unbind() { 180 if (observable != null) { 181 value = observable.getValue(); 182 observable.removeListener(listener); 183 observable = null; 184 } 185 } 186 187 /** 188 * Returns a string representation of this {@code ObjectPropertyBase} object. 189 * @return a string representation of this {@code ObjectPropertyBase} object. 190 */ 191 @Override 192 public String toString() { 193 final Object bean = getBean(); 194 final String name = getName(); 195 final StringBuilder result = new StringBuilder("ObjectProperty ["); 196 if (bean != null) { 197 result.append("bean: ").append(bean).append(", "); 198 } 199 if ((name != null) && (!name.equals(""))) { 200 result.append("name: ").append(name).append(", "); 201 } 202 if (isBound()) { 203 result.append("bound, "); 204 if (valid) { 205 result.append("value: ").append(get()); 206 } else { 207 result.append("invalid"); 208 } 209 } else { 210 result.append("value: ").append(get()); 211 } 212 result.append("]"); 213 return result.toString(); 214 } 215 216 private class Listener implements InvalidationListener { 217 @Override 218 public void invalidated(Observable valueModel) { 219 markInvalid(); 220 } 221 } 222}