/*
* 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) 2011 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.station.stack;
import java.awt.Component;
import java.awt.Dimension;
import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.action.DockAction;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.station.stack.tab.AbstractTabPaneComponent;
import bibliothek.gui.dock.station.stack.tab.LonelyTabPaneComponent;
import bibliothek.gui.dock.station.stack.tab.TabPane;
import bibliothek.gui.dock.station.stack.tab.TabPaneListener;
import bibliothek.gui.dock.station.stack.tab.layouting.LayoutBlock;
import bibliothek.gui.dock.station.stack.tab.layouting.Size;
import bibliothek.gui.dock.station.stack.tab.layouting.TabPlacement;
import bibliothek.gui.dock.station.stack.tab.layouting.Size.Type;
import bibliothek.gui.dock.themes.basic.action.buttons.ButtonPanel;
/**
* An {@link AbstractTabPaneComponent} that was specifically designed for showing a set of {@link DockAction}s.
* @author Benjamin Sigg
*/
public abstract class DockActionCombinedInfoComponent extends AbstractTabPaneComponent implements CombinedInfoComponent, LayoutBlock{
private CombinedStackDockComponent<?, ?, ?> pane;
private ButtonPanel buttons;
private Dockable dockable;
/** a listener that is added to {@link #pane} */
private TabPaneListener listener = new TabPaneListener(){
public void selectionChanged( TabPane pane ){
setSelection( pane.getSelectedDockable() );
}
public void removed( TabPane pane, Dockable dockable ){
// ignore
}
public void infoComponentChanged( TabPane pane, LonelyTabPaneComponent oldInfo, LonelyTabPaneComponent newInfo ){
// ignore
}
public void added( TabPane pane, Dockable dockable ){
// ignore
}
public void controllerChanged( TabPane pane, DockController controller ){
setController( controller );
}
};
/**
* Creates a new component.
* @param pane the owner of this info
*/
public DockActionCombinedInfoComponent( CombinedStackDockComponent<?, ?, ?> pane ){
super( pane );
this.pane = pane;
buttons = new ButtonPanel( true );
pane.addTabPaneListener( listener );
setController( pane.getController() );
}
/**
* Informs this component that it should release any remaining resources.
*/
public void destroy(){
pane.removeTabPaneListener( listener );
setController( null );
}
/**
* Sets the element whose actions should be shown on this info.
* @param dockable the item, can be <code>null</code>
*/
public void setSelection( Dockable dockable ){
this.dockable = dockable;
updateContent();
}
/**
* Gets the element which is currently shown on this info.
* @return the selected item, can be <code>null</code>
*/
public Dockable getSelection(){
return dockable;
}
/**
* Sets the {@link DockController} in whose realm this panel is used. This method is usually called
* automatically by the {@link TabPaneListener} that is added to the owner of this panel.
* @param controller the controller, can be <code>null</code>
*/
public void setController( DockController controller ){
buttons.setController( controller );
}
/**
* Using the current {@link DockController} and {@link Dockable}, this
* method updates the {@link DockActionSource} which selects the
* actions of this info.
*/
protected void updateContent(){
if( dockable == null ){
buttons.set( null, null );
}
else{
buttons.set( dockable, createActionSource( dockable ) );
}
}
/**
* Creates a new {@link DockActionSource} for <code>dockable</code>.
* @param dockable the element for which the actions are required
* @return the new source of actions
*/
protected abstract DockActionSource createActionSource( Dockable dockable );
@Override
public Component getComponent(){
return buttons;
}
public boolean isPaneVisible(){
return pane.getInfoHandler().isVisible( this );
}
public void setPaneVisible( boolean visible ){
pane.getInfoHandler().setVisible( this, visible );
}
public int getZOrder(){
return pane.getInfoHandler().getZOrder( this );
}
public void setZOrder( int order ){
pane.getInfoHandler().setZOrder( this, order );
}
public LayoutBlock toLayoutBlock(){
return this;
}
@Override
public void setOrientation( TabPlacement orientation ){
super.setOrientation( orientation );
buttons.setOrientation( orientation.toOrientation() );
}
public Size[] getSizes(){
Dimension[] sizes = buttons.getPreferredSizes();
Size[] result = new Size[ sizes.length ];
for( int i = 0; i < sizes.length; i++ ){
Type type;
if( i+1 == sizes.length )
type = Type.PREFERRED;
else
type = Type.MINIMUM;
result[i] = new CountingSize( type, sizes[i], i, (i+1) / (double)(sizes.length) );
}
return result;
}
public void setLayout( Size size ){
if( size instanceof CountingSize ){
buttons.setVisibleActions( ((CountingSize)size).getCount() );
}
else{
throw new IllegalArgumentException( "size not created by this component" );
}
}
public void setBounds( int x, int y, int width, int height ){
buttons.setBounds( x, y, width, height );
}
/**
* Size also counting the number of actions that are visible when applied.
* @author Benjamin Sigg
*/
private static class CountingSize extends Size{
private int count;
/**
* Creates a new size.
* @param type what kind of size this represents
* @param size the amount of pixels needed
* @param count the number of actions shown
* @param score how much this size is liked
*/
public CountingSize( Type type, Dimension size, int count, double score ){
super( type, size, score );
this.count = count;
}
/**
* Gets the number of actions that are shown.
* @return the number of actions
*/
public int getCount(){
return count;
}
}
}