All Downloads are FREE. Search and download functionalities are using the official Maven repository.

bibliothek.extension.gui.dock.preference.MergedPreferenceModel Maven / Gradle / Ivy

The newest version!
/*
 * 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) 2008 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
 * [email protected]
 * CH - Switzerland
 */
package bibliothek.extension.gui.dock.preference;

import java.util.ArrayList;
import java.util.List;

import bibliothek.gui.DockController;
import bibliothek.util.Path;
import bibliothek.util.PathCombiner;

/**
 * A preference model that envelops other models and uses their preferences. This model
 * makes use of a {@link PathCombiner} to create unique identifiers for all preferences of its
 * sub-models.
 * @author Benjamin Sigg
 */
public class MergedPreferenceModel extends AbstractPreferenceModel{
    private List models = new ArrayList();
    
    /** how to create the result of {@link #getPath(int)} */
    private PathCombiner combiner = PathCombiner.UNIQUE;
    
    private PreferenceModelListener listener = new PreferenceModelListener(){
        public void preferenceAdded( PreferenceModel model, int beginIndex, int endIndex ){
            int begin = indexAt( model, beginIndex );
            int end = begin + (endIndex - beginIndex);
            firePreferenceAdded( begin, end );
        }
        
        public void preferenceChanged( PreferenceModel model, int beginIndex, int endIndex ){
            int begin = indexAt( model, beginIndex );
            int end = begin + (endIndex - beginIndex);
            firePreferenceChanged( begin, end );
        }
        
        public void preferenceRemoved( PreferenceModel model, int beginIndex, int endIndex ){
            int begin = indexAt( model, beginIndex );
            int end = begin + (endIndex - beginIndex);
            firePreferenceRemoved( begin, end );
        }
    };
    
    /**
     * Creates a new model
     * @param controller the controller in whose realm this model is used
     */
    public MergedPreferenceModel( DockController controller ){
    	super( controller );
    }
    
    /**
     * Creates a new path.
     * @param combiner tells how to combine the path of a model and of
     * its preferences in {@link #getPath(int)}. Not null.
     * @param controller the controller in whose realm this model is used
     */
    public MergedPreferenceModel( PathCombiner combiner, DockController controller ){
    	super( controller );
        if( combiner == null )
            throw new IllegalArgumentException( "combiner must not be null" );
        
        this.combiner = combiner;
    }
    
    /**
     * Adds model at the end of this model.
     * @param model the additional model
     * @param path the location of the new model
     * @see #insert(int, PreferenceModel, Path)
     */
    public void add( PreferenceModel model, Path path ){
        insert( models.size(), model, path );
    }
    
    /**
     * Inserts a new submodel into this model.
     * @param index the location of the new model
     * @param model the new model
     * @param path the path of the new model, the path must be unique compared
     * to the paths of any other model.
     */
    public void insert( int index, PreferenceModel model, Path path ){
        if( this == model )
            throw new IllegalArgumentException( "model must not be this" );
        
        for( Model check : models ){
            if( check.model == model )
                throw new IllegalArgumentException( "can't add a model twice" );
            
            if( check.path.equals( path ))
                throw new IllegalArgumentException( "there is already a model with the path " + path );
        }
        
        Model insert = new Model();
        insert.model = model;
        insert.path = path;
        
        models.add( index, insert );
        if( hasListeners() )
            model.addPreferenceModelListener( listener );
        
        int size = model.getSize();

        if( size > 0 ){
            int begin = 0;
            for( int i = 0; i < index; i++ ){
                begin += models.get( i ).model.getSize();
            }
            firePreferenceAdded( begin, begin+size-1 );
        }
    }
    
    /**
     * Removes the index'th model of this merged model.
     * @param index the location of a child
     */
    public void remove( int index ){
        Model model = models.remove( index );
        if( hasListeners() )
            model.model.removePreferenceModelListener( listener );
        
        int size = model.model.getSize();
        if( size > 0 ){
            int begin = 0;
            for( int i = 0; i < index; i++ ){
                begin += models.get( i ).model.getSize();
            }
            firePreferenceRemoved( begin, begin+size-1 );
        }
    }
    
    /**
     * Removes model from this merged model.
     * @param model the model to remove
     */
    public void remove( MergedPreferenceModel model ){
        int index = indexOf( model );
        if( index >= 0 )
            remove( index );
    }
    
    /**
     * Removes the model with the path path.
     * @param path some path
     */
    public void remove( Path path ){
        int index = indexOf( path );
        if( index >= 0 )
            remove( index );        
    }
    
    /**
     * Removes all children from this model.
     */
    public void clear(){
        int size = getSize();
        if( hasListeners() ){
            for( Model model : models ){
                model.model.removePreferenceModelListener( listener );
            }
        }
        models.clear();
        if( size > 0 ){
            firePreferenceRemoved( 0, size-1 );
        }
    }
    
    /**
     * Gets the index of model.
     * @param model some model to search
     * @return the index or -1 if not found
     */
    public int indexOf( PreferenceModel model ){
        int i = 0;
        for( Model check : models ){
            if( check.model == model )
                return i;
            
            i++;
        }
        
        return -1;
    }
    
    /**
     * Gets the index of path.
     * @param path the path of some model
     * @return the index or -1 if not found
     */
    public int indexOf( Path path ){
        int i = 0;
        for( Model check : models ){
            if( check.path.equals( path ) )
                return i;
            
            i++;
        }
        
        return -1;
    }
    
    /**
     * Gets the index'th model of this merged model.
     * @param index some index
     * @return a child of this model
     */
    public PreferenceModel getModel( int index ){
        return models.get( index ).model;
    }
    
    /**
     * Gets the model which was stored using the key path.
     * @param path the path of the model
     * @return the model or null if not found
     */
    public PreferenceModel getModel( Path path ){
    	int index = indexOf( path );
    	if( index < 0 ){
    		return null;
    	}
    	return getModel( index );
    }
    
    @Override
    public void read() {
        for( Model model : models ){
            model.model.read();
        }
    }
    
    @Override
    public void write() {
        for( Model model : models ){
            model.model.write();
        }
    }
    
    @Override
    public void addPreferenceModelListener( PreferenceModelListener listener ) {
        boolean hadListeners = hasListeners();
        super.addPreferenceModelListener( listener );
        if( hasListeners() && !hadListeners ){
            for( Model model : models ){
                model.model.addPreferenceModelListener( this.listener );
            }
        }
    }
    
    @Override
    public void removePreferenceModelListener( PreferenceModelListener listener ) {
        boolean hadListeners = hasListeners();
        super.removePreferenceModelListener( listener );
        if( !hasListeners() && hadListeners ){
            for( Model model : models ){
                model.model.removePreferenceModelListener( this.listener );
            }
        }
    }
    
    public int getSize() {
        int size = 0;
        for( Model model : models ){
            size += model.model.getSize();
        }
        return size;
    }
    
    public String getLabel( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
        
        return local.model.model.getLabel( local.index );
    }
    
    @Override
    public String getDescription( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
        
        return local.model.model.getDescription( local.index );
    }
    
    public Object getValueInfo(int index) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
        
        return local.model.model.getValueInfo( local.index );
    }
    
    public Object getValue( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
        
        return local.model.model.getValue( local.index );
    }
    
    public void setValue( int index, Object value ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
        
        local.model.model.setValue( local.index, value );
    }
    
    public Path getTypePath( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
        
        return local.model.model.getTypePath( local.index );
    }
    
    public Path getPath( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
     
        return combiner.combine( local.model.path, local.model.model.getPath( local.index ) );
    }
    
    @Override
    public boolean isNatural( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
     
        return local.model.model.isNatural( local.index );
    }
    
    @Override
    public void setValueNatural( int index ) {
        Index local = indexAt( index );
        if( local == null )
            throw new ArrayIndexOutOfBoundsException( index );
     
        local.model.model.setValueNatural( local.index );   
    }
    
    /**
     * Gets the model and the index that globalIndex describe in
     * this model.
     * @param globalIndex some global index
     * @return the local index
     */
    protected Index indexAt( int globalIndex ){
        for( Model model : models ){
            int size = model.model.getSize();
            if( globalIndex < size )
                return new Index( model, globalIndex );
            else
                globalIndex -= size;
        }
        return null;
    }
    
    /**
     * Finds the global index if index is part of model.
     * @param model a child of this model
     * @param index an index in model
     * @return the global index
     */
    protected int indexAt( PreferenceModel model, int index ){
        for( Model check : models ){
            if( check.model == model )
                return index;
            
            index += check.model.getSize();
        }
        
        return index;
    }
    
    /**
     * Describes an index in one of the childen of a {@link MergedPreferenceModel}.
     * @author Benjamin Sigg
     */
    protected static class Index{
        public Model model;
        public int index;
        
        public Index( Model model, int index ){
            this.model = model;
            this.index = index;
        }
    }
    
    /**
     * A sub-model entry of a {@link MergedPreferenceModel}.
     * @author Benjamin Sigg
     */
    private static class Model{
        public PreferenceModel model;
        public Path path;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy