/*
* 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.dock.util.color.AbstractDockColor;
import bibliothek.util.Path;
/**
* An abstract implementation of {@link UIValue}. This class contains more than
* just one resource:
* <ul>
* <li>override: is a value that can be set from outside and overrides all other values</li>
* <li>value: is the value obtained through the {@link UIProperties}</li>
* <li>backup: is a value used when all other values are unavailable</li>
* </ul><br>
* This class also has methods to add or remove itself from a {@link UIProperties}.
*
* @author Benjamin Sigg
* @param <V> the kind of values this {@link UIValue} handles
* @param <U> the kind of {@link UIValue} that the {@link UIProperties} will handle.
* This class is either abstract, or a subclass of <code>U</code>.
*/
public abstract class AbstractUIValue<V, U extends UIValue<V>> implements UIValue<V> {
/** the value set by a client */
private V override;
/** the value set by a {@link UIProperties} */
private V value;
/** the backup value for emergencies */
private V backup;
/** the id for which this {@link UIValue} should listen */
private String id;
/** the kind of this {@link UIValue} */
private Path kind;
/** the current owner of this {@link UIValue} */
private UIProperties<V, U, ?> manager;
/** an override value of <code>null</code> is returned by {@link #value()} */
private boolean overrideNull = false;
/**
* Creates a new {@link UIValue}.
* @param id the id of the resource for which <code>this</code> should listen for
*/
public AbstractUIValue( String id ){
this( id, null, null );
}
/**
* Creates a new {@link UIValue}.
* @param id the id of the resource for which <code>this</code> should listen for
* @param kind the kind of {@link UIValue} this is
*/
public AbstractUIValue( String id, Path kind ){
this( id, kind, null );
}
/**
* Creates a new {@link UIValue}.
* @param id the id of the resource for which <code>this</code> should listen for
* @param backup a backup resource, can be <code>null</code>
*/
public AbstractUIValue( String id, V backup ){
this( id, null, backup );
}
/**
* Creates a new {@link UIValue}.
* @param id the id of the resource for which <code>this</code> should listen for
* @param kind the kind of {@link UIValue} this is, can be <code>null</code>
* @param backup a backup resource, can be <code>null</code>
*/
public AbstractUIValue( String id, Path kind, V backup ){
if( id == null )
throw new IllegalArgumentException( "id must no be null" );
if( kind == null )
throw new IllegalArgumentException( "kind must not be null" );
this.id = id;
this.kind = kind;
this.backup = backup;
}
/**
* Returns <code>this</code>. This method can only be implemented when
* the generic boundaries are met, so this methods ensures that <code>this</code>
* is really an <code>U</code>, or <code>abstract</code>.
* @return <code>this</code>
*/
protected abstract U me();
/**
* Changes the identifier of this value.
* @param id the new id, must not be <code>null</code>
*/
public void setId( String id ) {
if( id == null )
throw new IllegalArgumentException( "id must not be null" );
this.id = id;
if( this.manager != null ){
U me = me();
this.manager.remove( me );
this.manager.add( id, kind, me );
}
}
/**
* Gets the identifier of this value.
* @return the identifier, never <code>null</code>
*/
public String getId() {
return id;
}
/**
* Changes the kind of this value. The kind is used by the {@link UIProperties}
* to find out, which {@link UIBridge} should be used to interact with
* this {@link UIValue}.
* @param kind the new kind, not <code>null</code>. The kind should be
* a class or interfaces that is implemented by this {@link UIValue}.
*/
public void setKind( Path kind ) {
if( kind == null )
throw new IllegalArgumentException( "kind must not be null" );
this.kind = kind;
if( this.manager != null ){
U me = me();
this.manager.remove( me );
this.manager.add( id, kind, me );
}
}
/**
* Gets the kind of this value. See {@link #setKind(Path)}.
* @return the kind, never <code>null</code>
*/
public Path getKind() {
return kind;
}
/**
* Sets the manager which owns this {@link UIValue}, <code>this</code> will
* automatically be added or removed from the current <code>manager</code>.
* @param manager the new manager, can be <code>null</code>
*/
public void setManager( UIProperties<V, U, ?> manager ){
if( manager != this.manager ){
U me = me();
if( this.manager != null )
this.manager.remove( me );
this.manager = manager;
if( this.manager != null )
this.manager.add( id, kind, me );
}
}
public void set( V value ) {
V oldValue = value();
this.value = value;
V newValue = value();
if( oldValue != newValue ){
changed( oldValue, newValue );
}
}
/**
* Updates the value of this {@link UIValue} without actually installing <code>this</code>
* on <code>manager</code>.
* @param manager the manager from which to read the value
*/
public void update( UIProperties<V, U, ?> manager ){
manager.get( id, kind, me() );
}
/**
* Gets the first non-<code>null</code> value of the list
* <code>override</code>, <code>value</code>, <code>backup</code>.
* @return a resource or <code>null</code>
*/
public V value(){
if( overrideNull || override != null )
return override;
if( value != null )
return value;
return backup;
}
/**
* Called when the resource of this {@link AbstractDockColor} has changed
* @param oldValue the old value, can be <code>null</code>
* @param newValue the new value, can be <code>null</code>
*/
protected abstract void changed( V oldValue, V newValue );
/**
* Sets the override value.
* @param value the new override or <code>null</code>
*/
public void setValue( V value ) {
setValue( value, false );
}
/**
* Sets the override value. Please note that some modules won't work properly if {@link #value()} returns
* <code>null</code>, use <code>forceNull</code> with care.
* @param value the new value, can be <code>null</code>
* @param forceNull if <code>true</code> and <code>value</code> is <code>null</code>, then
* the result of {@link #value()} is <code>null</code> too
*/
public void setValue( V value, boolean forceNull ){
V oldValue = value();
this.override = value;
this.overrideNull = forceNull;
V newValue = value();
if( oldValue != newValue ){
changed( oldValue, newValue );
}
}
/**
* Gets the override value.
* @return the override or <code>null</code>
*/
public V getValue() {
return override;
}
/**
* Sets the backup value.
* @param backup the backup or <code>null</code>
*/
public void setBackup( V backup ) {
V oldColor = value();
this.backup = backup;
V newColor = value();
if( oldColor != newColor ){
changed( oldColor, newColor );
}
}
/**
* Gets the backup value.
* @return the backup or <code>null</code>
*/
public V getBackup() {
return backup;
}
}