/*
* 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) 2009 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.themes.basic;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.SwingUtilities;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.displayer.DisplayerCombinerTarget;
import bibliothek.gui.dock.station.DockableDisplayer;
import bibliothek.gui.dock.station.StationPaint;
import bibliothek.gui.dock.station.stack.StackDockComponent;
import bibliothek.gui.dock.station.support.CombinerSource;
import bibliothek.gui.dock.station.support.Enforcement;
import bibliothek.gui.dock.station.support.PlaceholderMap;
/**
* This {@link DisplayerCombinerTarget} can be used by {@link DockableDisplayer}s that show a
* {@link StackDockComponent} to paint some tabs. This target will create a {@link StackDockStation}
* if {@link #execute(CombinerSource)} is called.<br>
* Clients should first create an instance of this target, then call {@link #isValid()} to check whether
* the parameters were valid.
* @author Benjamin Sigg
*/
public class TabDisplayerCombinerTarget implements DisplayerCombinerTarget{
/** the index where the new dockable would be inserted */
private int index = -1;
/** the item that created this target */
private DockableDisplayer displayer;
/** the stack component used to paint a single dockable */
private StackDockComponent stack;
/**
* Creates a new target, clients should call {@link #isValid()} to check whether the new target can
* be executed.
* @param displayer the owner of this target
* @param stack the stack that shows exactly one {@link Dockable}
* @param source information about the {@link Dockable} that is going to be dropped
* @param force whether this target should be forced to be valid in more cases
*/
public TabDisplayerCombinerTarget( DockableDisplayer displayer, StackDockComponent stack, CombinerSource source, Enforcement force ){
this.displayer = displayer;
this.stack = stack;
Point mouse = source.getMousePosition();
if( mouse != null && stack != null && stack.getTabCount() == 1 ){
mouse = SwingUtilities.convertPoint( displayer.getDockable().getComponent(), mouse, stack.getComponent() );
Rectangle bounds = stack.getBoundsAt( 0 );
if( stack.getDockTabPlacement().isHorizontal() ){
if( bounds.y <= mouse.y && bounds.y + bounds.height >= mouse.y ){
if( bounds.x + bounds.width/2 < mouse.x ){
index = 1;
}
else{
index = 0;
}
}
else if( force.getForce() > 0.9f ){
index = 1;
}
}
else{
if( bounds.x <= mouse.x && bounds.x + bounds.width >= mouse.x ){
if( bounds.y + bounds.height/2 < mouse.y ){
index = 1;
}
else{
index = 0;
}
}
else if( force.getForce() > 0.9f ){
index = 1;
}
}
}
}
public boolean isValid(){
return index >= 0;
}
/**
* Gets the location where the {@link Dockable} would be inserted
* @return -1 if this target is invalid, otherwise 0 or 1
*/
public int getIndex(){
return index;
}
/**
* Gets the {@link Dockable} over which the new item would be dragged.
* @return the target {@link Dockable}, not <code>null</code>
*/
public Dockable getTarget(){
return displayer.getDockable();
}
public Dockable execute( CombinerSource source ){
DockStation parent = source.getParent();
PlaceholderMap placeholders = source.getPlaceholders();
StackDockStation stack = new StackDockStation( parent.getTheme() );
stack.setController( parent.getController() );
if( placeholders != null ){
stack.setPlaceholders( placeholders );
}
if( index == 1 ){
stack.drop( source.getOld(), false );
stack.drop( source.getNew(), false );
}
else{
stack.drop( source.getNew(), false );
stack.drop( source.getOld(), false );
}
return stack;
}
public void paint( Graphics g, Component component, StationPaint paint, Rectangle stationBounds, Rectangle dockableBounds ){
dockableBounds = new Rectangle( dockableBounds );
Rectangle tab = stack.getBoundsAt( 0 );
Point zero = new Point( 0, 0 );
zero = SwingUtilities.convertPoint( stack.getComponent(), zero, component );
tab.x += zero.x;
tab.y += zero.y;
int delta = 0;
switch( stack.getDockTabPlacement() ){
case TOP_OF_DOCKABLE:
delta = tab.y + tab.height - dockableBounds.y;
if( delta > 0 ){
dockableBounds.height -= delta;
dockableBounds.y += delta;
}
break;
case BOTTOM_OF_DOCKABLE:
delta = dockableBounds.y + dockableBounds.height - tab.y;
if( delta > 0 ){
dockableBounds.height -= delta;
}
break;
case LEFT_OF_DOCKABLE:
delta = tab.x + tab.width - dockableBounds.x;
if( delta > 0 ){
dockableBounds.width -= delta;
dockableBounds.x += delta;
}
break;
case RIGHT_OF_DOCKABLE:
delta = dockableBounds.x + dockableBounds.width - tab.x;
if( delta > 0 ){
dockableBounds.width -= delta;
}
break;
}
paint.drawInsertion( g, displayer.getStation(), stationBounds, dockableBounds );
if( stack.getDockTabPlacement().isHorizontal() ){
if( index == 0 ){
paint.drawInsertionLine( g, displayer.getStation(), tab.x, tab.y, tab.x, tab.y + tab.height );
}
else{
paint.drawInsertionLine( g, displayer.getStation(), tab.x + tab.width, tab.y, tab.x + tab.width, tab.y + tab.height );
}
}
else{
if( index == 0 ){
paint.drawInsertionLine( g, displayer.getStation(), tab.x, tab.y, tab.x + tab.width, tab.y );
}
else{
paint.drawInsertionLine( g, displayer.getStation(), tab.x, tab.y + tab.height, tab.x + tab.width, tab.y + tab.height );
}
}
}
public void paint( Graphics g, StationPaint paint ){
Dockable dockable = displayer.getDockable();
Point zeroDockable = new Point( 0, 0 );
SwingUtilities.convertPoint( displayer.getComponent(), zeroDockable, dockable.getComponent() );
paint.drawInsertion( g, displayer.getStation(), null, new Rectangle( zeroDockable, dockable.getComponent().getSize() ) );
}
}