package tutorial.core.basics;
import java.awt.Color;
import tutorial.support.ColorDockable;
import tutorial.support.JTutorialFrame;
import tutorial.support.Tutorial;
import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.control.relocator.Merger;
import bibliothek.gui.dock.control.relocator.MultiMerger;
import bibliothek.gui.dock.control.relocator.StackMerger;
import bibliothek.gui.dock.station.StationDropOperation;
import bibliothek.gui.dock.station.split.PutInfo;
import bibliothek.gui.dock.station.split.SplitDockGrid;
@Tutorial( id="Merger", title="Merge DockStations" )
public class MergerExample {
/* The framework knows classes that are DockStation and Dockable at the same time, for example the
* StackDockStation. When these objects are moved around, they are usually treated like a Dockable,
* and the framework completely ignores that they are in reality a group of Dockables.
*
* Sometimes this leads to layouts that do not look nice, for example a StackDockStation within
* another StackDockStation. With help of the interface "Merger" clients can implement custom rules of
* what is going to happen when a DockStation is dropped onto another DockStation.
*
* This example shows how a client can tell a SplitDockStation that dropping a StackDockStation onto
* a Dockable should not result in creating a new StackDockStation.
*/
public static void main( String[] args ){
/* Setting up a JFrame and a controller */
JTutorialFrame frame = new JTutorialFrame( MergerExample.class );
DockController controller = new DockController();
controller.setRootWindow( frame );
frame.destroyOnClose( controller );
/* Setting up our custom rules. The MultiMerger is just a collection containing other Mergers */
MultiMerger merger = new MultiMerger();
/* The StackMerger is the default Merger that is normally installed. It handles dropping
* StackDockStations onto StackDockStations */
merger.add( new StackMerger() );
/* Now we create our custom Merger */
merger.add( new CustomMerger() );
/* And by accessing the DockRelocator we can apply our new Merger */
controller.getRelocator().setMerger( merger );
/* Now we just set up some Dockable to play around with */
SplitDockStation station = new SplitDockStation();
controller.add( station );
frame.add( station );
SplitDockGrid grid = new SplitDockGrid();
grid.addDockable( 0, 0, 1, 1, new ColorDockable( "Red", Color.RED ) );
grid.addDockable( 0, 1, 1, 1, new ColorDockable( "Dark Red", Color.RED.darker() ) );
grid.addDockable( 1, 0, 1, 1, new ColorDockable( "Light Red", Color.RED.brighter() ) );
grid.addDockable( 1, 1, 1, 1, new ColorDockable( "Dark Green", Color.GREEN.darker() ) );
grid.addDockable( 1, 1, 1, 1, new ColorDockable( "Light Green", Color.GREEN.brighter() ) );
grid.addHorizontalDivider( 0, 2, 1 );
station.dropTree( grid.toTree() );
frame.setVisible( true );
}
/* This is our custom implementation of a Merger */
public static class CustomMerger implements Merger{
/* This method tells whether this Merger can do something meaningful with the
* given parent and child of a dropping operation */
public boolean canMerge( StationDropOperation operation, DockStation parent, DockStation child ){
if( parent instanceof SplitDockStation && child instanceof StackDockStation ){
SplitDockStation station = (SplitDockStation)parent;
PutInfo put = station.getDropInfo();
if( put != null && put.getCombinerTarget() != null ){
/* This merger only reacts if there is an operation in progress that would
* lead to a combination */
return true;
}
}
return false;
}
/* And this is our custom merging algorithm */
public void merge( StationDropOperation operation, DockStation parent, DockStation child ){
merge( (SplitDockStation)parent, (StackDockStation)child );
}
public void merge( SplitDockStation parent, StackDockStation child ){
/* Access the Dockable over which child is dropped */
PutInfo put = parent.getDropInfo();
Dockable old = put.getCombinerSource().getOld();
/* Remove child from its parent... */
if( child.getDockParent() != null ){
child.getDockParent().drag( child );
}
/* ... replace the old Dockable with the child... */
parent.replace( old, child );
/* ... and then add the old Dockable to the child */
child.add( old, 0 );
}
}
}