package tutorial.common.basics;
import java.awt.Color;
import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;
import tutorial.support.Tutorial;
import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.common.CContentArea;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.intern.AbstractDockableCStation;
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.intern.station.CommonDockStationFactory;
import bibliothek.gui.dock.common.mode.CNormalModeArea;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.common.perspective.CStationPerspective;
import bibliothek.gui.dock.facile.mode.Location;
import bibliothek.gui.dock.facile.mode.LocationMode;
import bibliothek.gui.dock.facile.mode.ModeAreaListener;
import bibliothek.gui.dock.layout.DockableProperty;
import bibliothek.gui.dock.support.mode.AffectedSet;
import bibliothek.gui.dock.util.DockUtilities;
import bibliothek.util.Path;
@Tutorial( id="NewCStation", title="Custom CStation")
public class NewCStationExample {
/* This example shows how a StackDockStation is converted into a dockable CStation that behaves like
* a working-area.
*
* This is only a skeleton example, in a real application some additional tweaking will
* be necessary to get everything running smoothly. */
public static void main( String[] args ){
/* Setting up a frame */
JTutorialFrame frame = new JTutorialFrame( NewCStationExample.class );
CControl control = new CControl( frame );
frame.destroyOnClose( control );
/* We do not want to move around the entire stack, so we change the group behavior */
control.setGroupBehavior( CGroupBehavior.TOPMOST );
/* Usually a CWorkingArea is not used alone but on top of a CContentArea, so we do the same
* in this example. */
CContentArea contentArea = control.getContentArea();
frame.add( contentArea );
/* We create our station and register it as root station */
CStack stack = new CStack( "stack" );
control.addStation( stack, true );
/* Now we set up some Dockable to play around with. The first three will be children of
* our station, the other three will represent "free" dockables. */
ColorSingleCDockable white = new ColorSingleCDockable( "White", Color.WHITE );
ColorSingleCDockable gray = new ColorSingleCDockable( "Gray", Color.GRAY );
ColorSingleCDockable black = new ColorSingleCDockable( "Black", Color.BLACK );
ColorSingleCDockable red = new ColorSingleCDockable( "Red", Color.RED );
ColorSingleCDockable green = new ColorSingleCDockable( "Green", Color.GREEN );
ColorSingleCDockable blue = new ColorSingleCDockable( "Blue", Color.BLUE );
/* We now put three Dockables and our custom station onto the CContentArea of our application. */
CGrid grid = new CGrid( control );
grid.add( 0, 0, 1, 0.25, red );
grid.add( 0, 0.25, 0.25, 0.25, green );
grid.add( 0, 0.5, 0.25, 0.5, blue );
grid.add( 0.25, 0.25, 0.75, 0.75, stack );
contentArea.deploy( grid );
/* Now we need to set up the remaining three Dockables. First we register them at the CControl. */
control.addDockable( white );
control.addDockable( gray );
control.addDockable( black );
/* Then we make sure, that they always stay on our custom station */
white.setWorkingArea( stack );
gray.setWorkingArea( stack );
black.setWorkingArea( stack );
/* We fall back to the Core API to make the Dockables visible. */
stack.getStation().add( white.intern(), 0 );
stack.getStation().add( gray.intern(), 1 );
stack.getStation().add( black.intern(), 2 );
frame.setVisible( true );
}
/* This is our custom CStation that is build upon a StackDockStation. By implementing
* CNormalModeArea we can register this station as an area with children in the "normal" mode. This is
* necessary in order for the CLocationManager to accept this station as a proper root-station.
*
* Our implementation is distributed over two classes: the CStack is a wrapper implementing CDockable and
* CStation. The CStackDockStation is the wrapped class that allows access to the API of Core.
*
* To make our life easier we extend from AbstractCDockableStation which already implements many methods
* of CDockable and CStation. */
private static class CStack extends AbstractDockableCStation<CStackDockStation> implements CNormalModeArea{
public CStack( String id ){
CStackDockStation delegate = new CStackDockStation( this );
CLocation stationLocation = new CLocation(){
@Override
public CLocation getParent(){
return null;
}
@Override
public String findRoot(){
return getUniqueId();
}
@Override
public DockableProperty findProperty( DockableProperty successor ){
return successor;
}
@Override
public ExtendedMode findMode(){
return ExtendedMode.NORMALIZED;
}
@Override
public CLocation aside(){
return this;
}
};
init( delegate, id, stationLocation, delegate );
}
/* This method is called by the CControl and allows access to some inner API that is
* hidden from normal clients. */
protected void install( CControlAccess access ){
access.getLocationManager().getNormalMode().add( this );
}
protected void uninstall( CControlAccess access ){
access.getLocationManager().getNormalMode().remove( getUniqueId() );
}
public CStationPerspective createPerspective(){
/* For this example we do not support perspectives. */
throw new IllegalStateException( "not implemented" );
}
public boolean isNormalModeChild( Dockable dockable ){
return isChild( dockable );
}
public DockableProperty getLocation( Dockable child ){
return DockUtilities.getPropertyChain( getStation(), child );
}
public boolean setLocation( Dockable dockable, DockableProperty location, AffectedSet set ){
set.add( dockable );
if( isChild( dockable )){
getStation().move( dockable, location );
}
else{
boolean acceptable = DockUtilities.acceptable( getStation(), dockable );
if( !acceptable ){
return false;
}
if( !getStation().drop( dockable, location )){
getStation().drop( dockable );
}
}
return true;
}
public void addModeAreaListener( ModeAreaListener listener ){
// not required
}
public Path getTypeId(){
// not required
return null;
}
public boolean autoDefaultArea(){
return true;
}
public boolean isLocationRoot(){
return true;
}
public boolean isChild( Dockable dockable ){
return dockable.getDockParent() == getStation();
}
public void removeModeAreaListener( ModeAreaListener listener ){
// not required
}
public void setController( DockController controller ){
// ignore
}
public void setMode( LocationMode mode ){
// ignore
}
public CLocation getCLocation( Dockable dockable ){
DockableProperty property = DockUtilities.getPropertyChain( getStation(), dockable );
return getStationLocation().expandProperty( getStation().getController(), property );
}
public CLocation getCLocation( Dockable dockable, Location location ){
DockableProperty property = location.getLocation();
if( property == null ){
return getStationLocation();
}
return getStationLocation().expandProperty( getStation().getController(), property );
}
public boolean respectWorkingAreas(){
return true;
}
public boolean isCloseable(){
return false;
}
public boolean isExternalizable(){
return false;
}
public boolean isMaximizable(){
return false;
}
public boolean isMinimizable(){
return false;
}
public boolean isStackable(){
return false;
}
public boolean isWorkingArea(){
return true;
}
public DockActionSource[] getSources(){
return new DockActionSource[]{ getClose() };
}
}
/* This is our Core DockStation. It needs to implement CommonDockable and CommonStation, that way the framework
* recognizes this object as beeing wrapped by some CDockable or CStation. */
private static class CStackDockStation extends StackDockStation implements CommonDockStation<StackDockStation,CStackDockStation>, CommonDockable{
private CStack delegate;
public CStackDockStation( CStack stack ){
this.delegate = stack;
}
@Override
public String getFactoryID(){
return CommonDockStationFactory.FACTORY_ID;
}
public String getConverterID(){
return super.getFactoryID();
}
public CDockable getDockable(){
return delegate;
}
public DockActionSource[] getSources(){
return delegate.getSources();
}
public CStation<CStackDockStation> getStation(){
return delegate;
}
public StackDockStation getDockStation(){
return this;
}
@Override
public CStackDockStation asDockStation(){
return this;
}
@Override
public CommonDockable asDockable(){
return this;
}
}
}