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

bibliothek.extension.gui.dock.station.SplitCombiner 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) 2010 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.station;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;

import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.ScreenDockStation;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.action.ListeningDockAction;
import bibliothek.gui.dock.displayer.DisplayerCombinerTarget;
import bibliothek.gui.dock.station.Combiner;
import bibliothek.gui.dock.station.StationPaint;
import bibliothek.gui.dock.station.split.SplitDockPathProperty;
import bibliothek.gui.dock.station.split.SplitDockPathProperty.Location;
import bibliothek.gui.dock.station.split.SplitNode;
import bibliothek.gui.dock.station.support.CombinerSource;
import bibliothek.gui.dock.station.support.CombinerTarget;
import bibliothek.gui.dock.station.support.Enforcement;
import bibliothek.gui.dock.station.support.PlaceholderMap;
import bibliothek.gui.dock.themes.basic.BasicCombiner;
import bibliothek.util.ClientOnly;

/**
 * This is an alternative implementation of a {@link Combiner}, normally not used by this framework. This
 * {@link Combiner} creates a {@link SplitDockStation} if the parent station is a {@link ScreenDockStation}.
 * @author Benjamin Sigg
 */
@ClientOnly
public class SplitCombiner extends BasicCombiner{
	public CombinerTarget prepare( CombinerSource source, Enforcement force ){
		if( source.isMouseOverTitle() || !(source.getParent() instanceof ScreenDockStation) ){
			return super.prepare( source, force );
		}
		
		Dimension size = source.getSize();
		Point position = source.getMousePosition();
		if( size == null || position == null ){
			return super.prepare( source, force );
		}
		if( isCentered(  size.width, size.height, position.x, position.y )){
			return super.prepare( source, force );
		}
		
		boolean topLeft = SplitNode.above( 0, size.height, size.width, 0, position.x, position.y );
		boolean topRight = SplitNode.above( 0, 0, size.width, size.height, position.x, position.y );
		
		Location put;
		if( topLeft && topRight ){
			put = Location.TOP;
		}
		else if( topLeft && !topRight ){
			put = Location.LEFT;
		}
		else if( !topLeft && topRight ){
			put = Location.RIGHT;
		}
		else{
			put = Location.BOTTOM;
		}
		
		Dimension newSize = source.getNew().getComponent().getSize();
		
		double oldSpace;
		double newSpace;
		double space;
		
		if( put == Location.LEFT || put == Location.RIGHT ){
			oldSpace = size.width;
			newSpace = newSize.width;
		}
		else{
			oldSpace = size.height;
			newSpace = newSize.height;
		}
		
		if( newSpace < 10 ){
			newSpace = 10;
		}
		if( newSpace + 10 > oldSpace ){
			newSpace = oldSpace - 10;
		}
		
		if( newSpace < 10 ){
			space = 0.5;
		}
		else{
			space = newSpace / oldSpace;
		}
		
		return new Target( source.getParent(), put, space );
	}
	
	/**
	 * Tells whether the position x/y is centered in width/height.
	 * @param width the width of some area
	 * @param height the height of some area
	 * @param x x-coordinate of a point 
	 * @param y y-coordinate of a point
	 * @return true if x/y is centered
	 */
	protected boolean isCentered( int width, int height, int x, int y ){
		if( x < width / 3 || x > width * 2 / 3 )
			return false;
		
		if( y < height / 3 || y > height * 2 / 3 )
			return false;
		
		return true;
	}

	public Dockable combine( CombinerSource source, CombinerTarget target ){
		if( target instanceof Target ){
			DockStation parent = source.getParent();
			PlaceholderMap placeholders = source.getPlaceholders();
			
			SplitDockStation split = new SplitDockStation(){
				@Override
				protected ListeningDockAction createFullScreenAction(){
					return null;
				}
			};
			split.setController( parent.getController() );
			split.updateTheme();
			
	        if( placeholders != null ){
	        	split.setPlaceholders( placeholders );
	        }
	        
	        split.drop( source.getOld() );
	        
	        Target splitTarget = (Target)target;
	        
	        SplitDockPathProperty location = new SplitDockPathProperty();
	        location.add( splitTarget.side, splitTarget.space, -1 );
	        
	        split.drop( source.getNew(), location );
	        return split;
		}
		else{
			return super.combine( source, target );
		}
	}

	/**
	 * Internal {@link CombinerTarget} of {@link SplitCombiner}, draws markings
	 * at one side of a {@link Dockable}.
	 * @author Benjamin Sigg
	 */
	private static class Target implements CombinerTarget{
		private DockStation station;
		private SplitDockPathProperty.Location side;
		private double space;
		
		/**
		 * Creates a new target.
		 * @param station the station associated with this target
		 * @param side the side at which the element will be added
		 * @param space the size of the new element
		 */
		public Target( DockStation station, SplitDockPathProperty.Location side, double space ){
			this.station = station;
			this.side = side;
			this.space = space;
		}
		
		public void paint( Graphics g, Component component, StationPaint paint, Rectangle stationBounds, Rectangle dockableBounds ){
			Rectangle destination = new Rectangle( dockableBounds );
			switch( side ){
				case TOP:
					destination.height = (int)(destination.height * space);
					break;
				case BOTTOM:
					destination.height = (int)(destination.height * space);
					destination.y += dockableBounds.height - destination.height;
					break;
				case LEFT:
					destination.width = (int)(destination.width * space);
					break;
				case RIGHT:
					destination.width = (int)(destination.width * space);
					destination.x += dockableBounds.width - destination.width;
			}
			
			paint.drawInsertion( g, station, dockableBounds, destination );
		}
		
		public DisplayerCombinerTarget getDisplayerCombination(){
			return null;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy