/*
* 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) 2012 Herve Guillaume, 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
*
* Herve Guillaume
* rvguillaume@hotmail.com
* FR - France
*
* Benjamin Sigg
* benjamin_sigg@gmx.ch
* CH - Switzerland
*/
package bibliothek.gui.dock.station.toolbar;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.LayoutManager2;
import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.Orientation;
import bibliothek.gui.dock.ToolbarDockStation;
import bibliothek.gui.dock.station.span.Span;
import bibliothek.gui.dock.station.span.SpanCallback;
import bibliothek.gui.dock.station.span.SpanMode;
import bibliothek.gui.dock.station.span.SpanUsage;
import bibliothek.gui.dock.themes.StationSpanFactoryValue;
import bibliothek.gui.dock.themes.ThemeManager;
/**
* {@link LayoutManager} used by the {@link ToolbarDockStation}.
* @author Benjamin Sigg
*/
public abstract class SpanToolbarLayoutManager implements LayoutManager2{
private ToolbarDockStation station;
private Container parent;
private Span[] spans = new Span[]{};
private StationSpanFactoryValue factory;
private int size;
private int index = -1;
private int gap = 3;
private int sideGap = 5;
public SpanToolbarLayoutManager( ToolbarDockStation station, Container parent ){
this.parent = parent;
this.station = station;
factory = new StationSpanFactoryValue( ThemeManager.SPAN_FACTORY + ".toolbar", station ){
@Override
protected void changed(){
reset();
}
};
}
/**
* Gets the size of the gap between each child component.
* @return the gap size
*/
public int getGap(){
return gap;
}
/**
* Sets the size of the gap between each child component.
* @param gap the size of the gap, at least 0
*/
public void setGap( int gap ){
if( gap < 0 ){
throw new IllegalArgumentException( "gap must not be smaller than 0" );
}
this.gap = gap;
}
/**
* Gets the size of the gap between the children and the outside border.
* @return the size of the gap
*/
public int getSideGap(){
return sideGap;
}
/**
* Sets the size of the gap between the children and the outside border.
* @param sideGap the size of the gap, at least 0
*/
public void setSideGap( int sideGap ){
if( sideGap < 0 ){
throw new IllegalArgumentException( "sideGap must not be smaller than 0" );
}
this.sideGap = sideGap;
}
public void setController( DockController controller ){
factory.setController( controller );
}
/**
* Calculates where to insert an item assuming the mouse is at position <code>x/y</code>.
* @param x the x coordinate of the mouse
* @param y the y coordinate of the mouse
* @return the preferred position to insert a new {@link Dockable}
*/
public int getInsertionIndex( int x, int y ){
if( station.getDockableCount() == 0 ){
return 0;
}
int[] positions = new int[parent.getComponentCount()];
int location;
if( station.getOrientation() == Orientation.HORIZONTAL ){
location = x;
for( int i = 0; i < positions.length; i++ ){
Component child = parent.getComponent( i );
positions[i] = child.getX() + child.getWidth()/2;
}
}
else{
location = y;
for( int i = 0; i < positions.length; i++ ){
Component child = parent.getComponent( i );
positions[i] = child.getY() + child.getHeight()/2;
}
}
for( int i = 0; i < positions.length; i++ ){
if( location <= positions[i] ){
return i;
}
}
return positions.length;
}
public void setSpanSize( Dockable moved ){
Dimension dim = moved.getComponent().getPreferredSize();
int size;
if( station.getOrientation() == Orientation.HORIZONTAL ){
size = dim.width;
}
else{
size = dim.height;
}
if( this.size != size ){
this.size = size;
for( Span span : spans ){
span.configureSize( SpanMode.OPEN, size );
}
}
}
public void setExpandedSpan( int index, boolean mutate ){
if( this.index != index ){
this.index = index;
if( mutate ){
for( int i = 0; i < spans.length; i++ ){
if( i == index ){
spans[i].mutate( SpanMode.OPEN );
}
else{
spans[i].mutate( SpanMode.OFF );
}
}
}
else{
for( int i = 0; i < spans.length; i++ ){
if( i == index ){
spans[i].set( SpanMode.OPEN );
}
else{
spans[i].set( SpanMode.OFF );
}
}
}
}
}
protected abstract void revalidate();
private void reset(){
index = -1;
int count = station.getDockableCount()+1;
if( spans.length != count ){
SpanCallback callback = new SpanCallback(){
@Override
public DockStation getStation(){
return station;
}
@Override
public boolean isHorizontal(){
return station.getOrientation() == Orientation.HORIZONTAL;
}
@Override
public boolean isVertical(){
return station.getOrientation() == Orientation.VERTICAL;
}
@Override
public void resized(){
revalidate();
}
@Override
public SpanUsage getUsage(){
return SpanUsage.INSERTING;
}
};
spans = new Span[ count ];
for( int i = 0; i < count; i++ ){
spans[i] = factory.create( callback );
spans[i].configureSize( SpanMode.OPEN, size );
}
}
}
@Override
public void addLayoutComponent( String name, Component comp ){
reset();
}
@Override
public void removeLayoutComponent( Component comp ){
reset();
}
@Override
public Dimension preferredLayoutSize( Container parent ){
Insets insets = parent.getInsets();
int deltaWidth = 0;
int deltaHeight = 0;
if( insets != null ){
deltaWidth += insets.left + insets.right;
deltaHeight += insets.top + insets.bottom;
}
if( station.getOrientation() == Orientation.HORIZONTAL ){
int width = 0;
int height = 0;
for( int i = 0, n = parent.getComponentCount(); i<n; i++ ){
Component child = parent.getComponent( i );
Dimension size = child.getPreferredSize();
width += size.width;
if( i == 0 ){
width += sideGap;
}
else{
width += gap;
}
height = Math.max( height, size.height );
}
width += sideGap;
for( Span span : spans ){
width += span.getSize();
}
return new Dimension( width + deltaWidth, height+2*sideGap + deltaHeight );
}
else{
int width = 0;
int height = 0;
for( int i = 0, n = parent.getComponentCount(); i<n; i++ ){
Component child = parent.getComponent( i );
Dimension size = child.getPreferredSize();
height += size.height;
if( i == 0 ){
height += sideGap;
}
else{
height += gap;
}
width = Math.max( width, size.width );
}
height += sideGap;
for( Span span : spans ){
height += span.getSize();
}
return new Dimension( width+2*sideGap + deltaWidth, height + deltaHeight );
}
}
@Override
public Dimension minimumLayoutSize( Container parent ){
return preferredLayoutSize( parent );
}
@Override
public void layoutContainer( Container parent ){
Insets insets = parent.getInsets();
int x = 0;
int y = 0;
int width = parent.getWidth();
int height = parent.getHeight();
if( insets != null ){
x = insets.left;
y = insets.top;
width -= insets.left + insets.right;
height -= insets.top + insets.bottom;
width = Math.max( width, 1 );
height = Math.max( height, 1 );
}
if( station.getOrientation() == Orientation.HORIZONTAL ){
for( int i = 0, n = parent.getComponentCount(); i<n; i++ ){
int span = 0;
if( i < spans.length ){
span = spans[i].getSize();
}
x += span;
if( i == 0 ){
x += sideGap;
}
else{
x += gap;
}
Component comp = parent.getComponent( i );
Dimension size = comp.getPreferredSize();
comp.setBounds( x, y+sideGap, size.width, height-2*sideGap );
x += size.width;
}
}
else{
for( int i = 0, n = parent.getComponentCount(); i<n; i++ ){
int span = 0;
if( i < spans.length ){
span = spans[i].getSize();
}
y += span;
if( i == 0 ){
y += sideGap;
}
else{
y += gap;
}
Component comp = parent.getComponent( i );
Dimension size = comp.getPreferredSize();
comp.setBounds( x+sideGap, y, width-2*sideGap, size.height );
y += size.height;
}
}
}
@Override
public void addLayoutComponent( Component comp, Object constraints ){
reset();
}
@Override
public Dimension maximumLayoutSize( Container target ){
return preferredLayoutSize( target );
}
@Override
public float getLayoutAlignmentX( Container target ){
return 0;
}
@Override
public float getLayoutAlignmentY( Container target ){
return 0;
}
@Override
public void invalidateLayout( Container target ){
// ihnotr
}
}