/*
* Bibliothek - DockingFrames
* Library built on Java/Swing, allows the user to "drag and drop"
* panels containing any Swing-Component the developer likes to add.
*
* Copyright (C) 2007 Benjamin Sigg
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Benjamin Sigg
* benjamin_sigg@gmx.ch
* CH - Switzerland
*/
package bibliothek.gui.dock.util;
import bibliothek.gui.DockController;
/**
* A wrapper for a value which is either read from {@link DockProperties},
* or can be set by the client directly.
* @author Benjamin Sigg
*
* @param <A> the type of wrapper value
*/
public abstract class PropertyValue<A> {
/** the access to the value */
private PropertyKey<A> key;
/** the observed properties, can be <code>null</code> */
private DockProperties properties;
/** the value set by the client */
private A value;
/** a listener to {@link #properties} */
private DockPropertyListener<A> listener;
/**
* Creates a new value.
* @param key the key used to access the value in {@link DockProperties}
*/
public PropertyValue( PropertyKey<A> key ){
this( key, null );
}
/**
* Creates a new value.
* @param key the key used to access the value in {@link DockProperties}
* @param controller the controller from which properties are to be read
*/
public PropertyValue( PropertyKey<A> key, DockController controller ){
if( key == null )
throw new IllegalArgumentException( "Key must not be null" );
this.key = key;
listener = new DockPropertyListener<A>(){
public void propertyChanged( DockProperties properties, PropertyKey<A> property, A oldValue, A newValue ){
if( value == null )
valueChanged( oldValue, newValue );
}
};
setProperties( controller );
}
/**
* Sets the {@link DockProperties} that are read from
* <code>controller</code>.
* @param controller the properties, can be <code>null</code>
* @see #setProperties(DockProperties)
*/
public void setProperties( DockController controller ){
if( controller == null )
setProperties( (DockProperties)null );
else
setProperties( controller.getProperties() );
}
/**
* Sets the {@link DockProperties} which should be observed.
* @param properties the new properties, can be <code>null</code>
*/
public void setProperties( DockProperties properties ){
if( value != null )
this.properties = properties;
else{
A oldValue = getValue();
if( this.properties != null )
this.properties.removeListener( key, listener );
this.properties = properties;
if( properties != null )
properties.addListener( key, listener );
A newValue = getValue();
if( (oldValue == null && newValue != null) ||
(oldValue != null && newValue == null) ||
(oldValue != null && !oldValue.equals( newValue ))){
valueChanged( oldValue, newValue );
}
}
}
/**
* Gets the currently observed properties.
* @return the map, or <code>null</code>
*/
public DockProperties getProperties(){
return properties;
}
/**
* Gets the key which is used to access the value in {@link DockProperties}.
* @return the key
*/
public PropertyKey<A> getKey(){
return key;
}
/**
* Sets the key which is used to access the value in {@link DockProperties}.
* @param key the new key
*/
public void setKey( PropertyKey<A> key ) {
if( key == null )
throw new IllegalArgumentException( "key must not be null" );
if( properties == null ){
this.key = key;
}
else{
A oldValue = getValue();
properties.removeListener( this.key, listener );
this.key = key;
properties.addListener( this.key, listener );
A newValue = getValue();
if( (oldValue == null && newValue != null) ||
(oldValue != null && newValue == null) ||
(oldValue != null && !oldValue.equals( newValue ))){
valueChanged( oldValue, newValue );
}
}
}
/**
* Gets the current value. The result is the argument of {@link #setValue(Object)} if
* the argument was not <code>null</code>, or else the value read from
* the {@link #setProperties(DockProperties) properties}.<br>
* Note that this method can return <code>null</code> even if the
* {@link PropertyKey} has a non-<code>null</code> default value.
* @return the value or <code>null</code> if no value was found at all
*/
public A getValue(){
if( value != null )
return value;
if( properties != null )
return properties.get( key );
return key.getDefault( null );
}
/**
* Gets the value that was set through {@link #setValue(Object)}.
* @return the value, might be <code>null</code>
*/
public A getOwnValue(){
return value;
}
/**
* Tells whether any value is set.
* @return <code>true</code> if not the default value of the key
* would be returned
*/
public boolean isAnyValueSet(){
if( value != null )
return true;
if( properties != null ){
if( properties.isSet( key ))
return true;
}
return false;
}
/**
* Sets the current value.
* @param value the value, <code>null</code> if the value should be read
* from the {@link #setProperties(DockProperties) properties}
*/
public void setValue( A value ){
if( properties != null ){
if( this.value == null && value != null )
properties.removeListener( key, listener );
else if( this.value != null && value == null )
properties.addListener( key, listener );
}
A oldValue = getValue();
this.value = value;
A newValue = getValue();
if( (oldValue == null && newValue != null) ||
(oldValue != null && newValue == null) ||
(oldValue != null && !oldValue.equals( newValue ))){
valueChanged( oldValue, newValue );
}
}
/**
* Invoked when the value has been changed.
* @param oldValue the new value
* @param newValue the old value
*/
protected abstract void valueChanged( A oldValue, A newValue );
@Override
public String toString(){
return getClass().getName() + "[" + key.toString() + " -> " + getValue() + "]";
}
}