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

bibliothek.gui.dock.support.menu.SeparatingMenuPiece Maven / Gradle / Ivy

The newest version!
package bibliothek.gui.dock.support.menu;

import java.awt.Component;
import java.util.List;

import javax.swing.JPopupMenu;

/**
 * A piece which envelops another piece with separators.
 * @author Benjamin Sigg
 */
public class SeparatingMenuPiece extends MenuPiece{
	/** whether to make a separator above this menupiece or not */
    private boolean topSeparator = false;
    /** whether to make a separator below this menupiece or not */
    private boolean bottomSeparator = false;
    /** whether to show a separator when there are no items in this menupiece */
    private boolean emptySeparator = false;
    
    /** the separator shown at the top */
    private Component separatorTop = null;
    /** the separator shown at the bottom */
    private Component separatorBottom = null;
    
    /** the source of items */
    private MenuPiece piece;
    /** a listener used to add or remove items */
    private Listener listener = new Listener();
    
    /**
     * Creates a new piece
     */
    public SeparatingMenuPiece(){
    	this( null );
    }

    
    /**
     * Creates a new piece
     * @param topSeparator whether to show a separator at the top
     * @param emptySeparator whether to show a separator if piece is empty
     * @param bottomSeparator whether to show a separator at the bottom
     */
    public SeparatingMenuPiece( boolean topSeparator, boolean emptySeparator, boolean bottomSeparator ){
    	this( null, topSeparator, emptySeparator, bottomSeparator );
    }
    
    /**
     * Creates a new piece
     * @param piece the piece which might be covered by separators
     */
    public SeparatingMenuPiece( MenuPiece piece ){
    	this( piece, false, false, false );
    }
    
    /**
     * Creates a new piece
     * @param piece the piece which might be covered by separators
     * @param topSeparator whether to show a separator at the top
     * @param emptySeparator whether to show a separator if piece is empty
     * @param bottomSeparator whether to show a separator at the bottom
     */
    public SeparatingMenuPiece( MenuPiece piece, boolean topSeparator, boolean emptySeparator, boolean bottomSeparator ){
    	setPiece( piece );
    	setTopSeparator( topSeparator );
    	setEmptySeparator( emptySeparator );
    	setBottomSeparator( bottomSeparator );
    }
    
    
    /**
     * Gets the piece which is embraced by separators.
     * @return the piece
     */
    public MenuPiece getPiece(){
		return piece;
	}
    
    @Override
    public void bind(){
    	super.bind();
    	piece.bind();
    }
    
    @Override
    public void unbind(){
    	super.unbind();
    	piece.unbind();
    }
    
    /**
     * Sets the piece which will be embraced by separators.
     * @param piece the child of this piece
     */
    public void setPiece( MenuPiece piece ){
    	if( this.piece != piece ){
    		if( this.piece != null ){
    			listener.remove( piece, 0, piece.getItemCount() );
    			this.piece.setParent( null );
    			piece.removeListener( listener );
    		}
    		
        	this.piece = piece;
        	
        	if( this.piece != null ){
        		piece.setParent( this );
        		piece.addListener( listener );
        		listener.insert( piece, 0, piece.items() );
        	}
    	}
	}
    
    @Override
    public int getItemCount(){
    	if( piece == null ){
    		return getSeparatorCount();
    	}
    	return piece.getItemCount() + getSeparatorCount();
    }
        
    @Override
    public void fill( List items ){
    	if( piece == null || piece.getItemCount() == 0 ){
    		if( emptySeparator )
    			items.add( getEmptySeparator() );
    	}
    	else{
    		if( topSeparator )
    			items.add( getTopSeparator() );
    		
    		piece.fill( items );
    		
    		if( bottomSeparator )
    			items.add( getBottomSeparator() );
    	}
    }
    
    /**
     * Gets the number of separators which were added by this piece.
     * @return the number of separators
     */
    protected int getSeparatorCount(){
    	if( piece != null && piece.getItemCount() > 0 ){
    		if( topSeparator && bottomSeparator )
    			return 2;
    		
    		if( topSeparator || bottomSeparator )
    			return 1;
    		
    		return 0;
    	}
    	else{
    		if( emptySeparator )
    			return 1;
    		
    		return 0;
    	}
    }
    
    /**
     * Tells whether there is a separator below this piece.
     * @return true if there is a separator
     * @see #setBottomSeparator(boolean)
     */
    public boolean isBottomSeparator() {
        return bottomSeparator;
    }
    
    /**
     * Sets whether there should be a separator added to the menu after
     * the contents described in this piece. Note that there might not be
     * any separator if this piece is empty.
     * @param bottomSeparator true if there should be a separator
     */
    public void setBottomSeparator( boolean bottomSeparator ) {
        if( this.bottomSeparator != bottomSeparator ){
            this.bottomSeparator = bottomSeparator;
            putUpSeparators();
            
            MenuPiece parent = getParent();
            if( parent != null ){
	            if( piece != null && piece.getItemCount() > 0 ){
	                if( bottomSeparator ){
	                	fireInsert( getItemCount(), getBottomSeparator() );
	                }
	                else{
	                	fireRemove( getItemCount()-1, 1 );
	                }
	            }
            }
        }
    }
    
    /**
     * Tells whether there should be a single separator shown when this
     * piece is empty.
     * @return true if there is a separator
     */
    public boolean isEmptySeparator() {
        return emptySeparator;
    }
    
    /**
     * Sets whether there should be a separator shown when this piece
     * is empty.
     * @param emptySeparator true if a separator should be
     * made visible
     */
    public void setEmptySeparator( boolean emptySeparator ) {
        if( this.emptySeparator != emptySeparator ){
            this.emptySeparator = emptySeparator;
            putUpSeparators();
            
            if( piece == null || piece.getItemCount() == 0 ){
                if( emptySeparator ){
                	fireInsert( 0, getEmptySeparator() );
                }
                else{
                	fireRemove( 0, 1 );
                }
            }
        }
    }
    
    /**
     * Tells whether there is a separator shown above the content of this
     * piece.
     * @return true if there is a separator
     */
    public boolean isTopSeparator() {
        return topSeparator;
    }
    
    /**
     * Sets whether there should be a separator shown above the content of
     * this piece. Note that there might not be any separator if this piece
     * is empty.
     * @param topSeparator true if the separator should be shown
     */
    public void setTopSeparator( boolean topSeparator ) {
        if( this.topSeparator != topSeparator ){
            this.topSeparator = topSeparator;
            putUpSeparators();
            
            if( piece != null && piece.getItemCount() > 0 ){
            	if( topSeparator ){
                	fireInsert( 0, getTopSeparator() );
                }
                else{
                	fireRemove( 0, 1 );
                }
            }
        }
    }
    
    /**
     * Gets the separator which is shown at the top.
     * @return the separator or null if no separator is needed
     */
    private Component getTopSeparator(){
    	return separatorTop;
    }

    /**
     * Gets the separator which is shown at the bottom.
     * @return the separator or null if no separator is needed
     */
    private Component getBottomSeparator(){
    	return separatorBottom;
    }
    
    /**
     * Gets the separator which is shown at when this piece is empty.
     * @return the separator or null if no separator is needed
     */
    private Component getEmptySeparator(){
    	if( separatorTop != null )
    		return separatorTop;
    	else
    		return separatorBottom;
    }
    
    /**
     * Makes sure that there all separators needed for the menu are available. 
     */
    private void putUpSeparators(){
    	boolean top = topSeparator;
    	boolean bottom = bottomSeparator;
    	
    	if( emptySeparator ){
    		if( !top && !bottom )
    			top = true;
    	}
    	
    	if( top && separatorTop == null )
    		separatorTop = new JPopupMenu.Separator();
    	else if( !top && separatorTop != null )
    		separatorTop = null;
    	
    	if( bottom && separatorBottom == null )
    		separatorBottom = new JPopupMenu.Separator();
    	else if( !top && separatorBottom != null )
    		separatorBottom = null;
    }
    
	/**
	 * A listener to all children, forwarding any call of inserting or removing
	 * items.
	 * @author Benjamin Sigg
	 */
	private class Listener implements MenuPieceListener{
	    public void insert( MenuPiece child, int index, Component... component ){
	    	if( component.length > 0 ){
		    	int count = piece.getItemCount() - component.length;
		    	if( count == 0 ){
		    		if( emptySeparator  )
		    			fireRemove( 0, 1 );
		    		
		    		if( bottomSeparator )
		    			fireInsert( 0, getBottomSeparator() );
		    		
		    		if( topSeparator )
		    			fireInsert( 0, getTopSeparator() );
		    	}
		    	
	    		if( topSeparator )
		    		index++;
		    	
		    	fireInsert( index, component );
	    	}
	    }
	    
	    public void remove( MenuPiece child, int index, int length ){
	    	if( length > 0 ){
	    		if( topSeparator )
	    			index++;
	    	
	    		fireRemove( index, length );
	    		
	    		if( child.getItemCount() == 0 ){
	    			if( topSeparator && bottomSeparator ){
	    				fireRemove( 0, 2 );
	    			}
	    			else if( topSeparator || bottomSeparator ){
	    				fireRemove( 0, 1 );
	    			}
	    			
	    			if( emptySeparator )
	    				fireInsert( 0, getEmptySeparator() );
	    		}
	    	}
	    }
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy