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

bibliothek.gui.dock.common.intern.ui.WorkingAreaAcceptance Maven / Gradle / Ivy

Go to download

DockingFrames is an open source Java Swing docking framework, licenced under LGPL 2.1. This is the same distribution as the original distribution (http://www.docking-frames.org/), only reinstalled in maven

There is a newer version: 1.1.2p20b.fix-1
Show 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) 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
 * [email protected]
 * CH - Switzerland
 */
package bibliothek.gui.dock.common.intern.ui;

import java.util.HashSet;
import java.util.Set;

import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.DockElement;
import bibliothek.gui.dock.accept.DockAcceptance;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.group.CGroupMovement;
import bibliothek.gui.dock.common.intern.CControlAccess;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.station.CommonDockStation;
import bibliothek.gui.dock.common.mode.CLocationMode;
import bibliothek.gui.dock.common.mode.CLocationModeManager;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.util.DockUtilities;
import bibliothek.gui.dock.util.DockUtilities.DockVisitor;
import bibliothek.util.FrameworkOnly;

/**
 * A {@link DockAcceptance} ensuring that the {@link CDockable#getWorkingArea()}
 * property is respected.
 * @author Benjamin Sigg
 */
@FrameworkOnly
public class WorkingAreaAcceptance implements DockAcceptance {
    /** access to the inner parts of the {@link CControl} */
    private CControlAccess control;
    
    /**
     * Creates a new acceptance
     * @param control access to the {@link CControl}
     */
    public WorkingAreaAcceptance( CControlAccess control ){
        this.control = control;
    }

    public boolean accept( DockStation parent, Dockable child, Dockable next ) {
    	if( accept( parent, next ) ){
    		return getWorkingArea( child, true ) == getWorkingArea( next, true );
    	}
    	else {
    		return false;
    	}
    }
    
    public boolean accept( DockStation parent, Dockable child ) {
    	CLocationModeManager manager = control.getLocationManager();
    	if( manager.isOnTransaction() ){
    		CGroupMovement action = manager.getCurrentAction();
    		if( action == null || action.forceAccept( parent, child )){
    			return true;
    		}
    	}
    	
    	ExtendedMode extendedMode = manager.childsExtendedMode( parent );
    	if( extendedMode == null ){
    		extendedMode = manager.getMode( child );	
    		if( extendedMode == null ){
    			return true;
    		}
    	}
    	
    	CLocationMode mode = manager.getMode( extendedMode.getModeIdentifier() );
    	if( mode == null )
    		return true;
    	
    	if( !mode.respectWorkingAreas( parent ) ){
    		return true;
    	}
    	
    	CStation area = searchArea( parent );
    	return match( area, child );
    }
    
    /**
     * Searches the first {@link CStation} with the working-area property set to true in the path to the root.
     * @param element some element
     * @return the first {@link CStation} that occurs on the path from
     * element to the root and which is a working area
     */
    private CStation searchArea( DockElement element ){
        DockStation station = element.asDockStation();
        Dockable dockable = element.asDockable();
        
        while( dockable != null || station != null ){
            if( station instanceof CommonDockStation){
            	CStation cstation = ((CommonDockStation)station).getStation();
                if( cstation.isWorkingArea() )
                    return cstation;
            }
            
            dockable = station == null ? null : station.asDockable();
            station = dockable == null ? null : dockable.getDockParent();
        }
        return null;
    }
    
    /**
     * Checks all {@link CDockable}s and compares their
     * {@link CDockable#getWorkingArea() working area}
     * with area.
     * @param area a possible new parent
     * @param dockable the root of the tree of elements to test
     * @return true if all elements have area as
     * preferred parent, false otherwise
     */
    private boolean match( CStation area, Dockable dockable ){
        if( dockable instanceof CommonDockable ){
        	CStation expectedWorkingArea = getWorkingArea( dockable, false );
        	CDockable self = ((CommonDockable)dockable).getDockable();
        	
			if( expectedWorkingArea != area && expectedWorkingArea != self )
				// if we are moving a CWorkingArea around, then 'exectedWorkingArea == self'
                return false;
        }
        
        DockStation station = dockable.asDockStation();
        if( station != null ){
        	if( dockable instanceof CommonDockable ){
        		CStation cstation = ((CommonDockable)dockable).getStation();
        		if( cstation != null && cstation.isWorkingArea() ){
        			return true;
        		}
        	}
        	
            return match( area, station );
        }
        else
            return true;
    }
    
    private CStation getWorkingArea( Dockable dockable, boolean excludeSelf ){
    	final Set> workingAreas = new HashSet>();
    	
    	DockUtilities.visit( dockable, new DockVisitor() {
    		@Override
    		public void handleDockable( Dockable dockable ) {
    			if( dockable instanceof CommonDockable ){
    		    	CDockable fdockable = ((CommonDockable)dockable).getDockable();
    		    	CStation workingArea = fdockable.getWorkingArea();
    		    	if( workingArea != null ){
    		    		workingAreas.add( workingArea );
    		    	}
    	    	}
    		}
		});
    	
    	if( dockable instanceof CommonDockable ){
    		CStation station = ((CommonDockable) dockable).getDockable().asStation();
    		if( station != null && station.isWorkingArea() ){
    			workingAreas.remove( station );
    		}
    	}
    	
    	if( workingAreas.size() == 1 ){
    		return workingAreas.iterator().next();
    	}
    	else{
    		return null;
    	}
    }
    
    /**
     * Checks all {@link CDockable}s and compares their
     * {@link CDockable#getWorkingArea() working area}
     * with area.
     * @param area a possible new parent
     * @param station the root of the tree of elements to test
     * @return true if all elements have area as
     * preferred parent, false otherwise
     */
    private boolean match( CStation area, DockStation station ){
        for( int i = 0, n = station.getDockableCount(); i < n; i++ ){
            boolean result = match( area, station.getDockable( i ));
            if( !result )
                return false;
        }
        return true;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy