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.SingleParentRemover;
import bibliothek.gui.dock.station.split.DockableSplitDockTree;
import bibliothek.gui.dock.station.split.SplitDockGrid;
import bibliothek.gui.dock.station.split.SplitDockProperty;
import bibliothek.gui.dock.station.stack.StackDockProperty;
@Tutorial(title="SplitDockStation", id="SplitDockStation")
public class SplitDockStationExample {
public static void main( String[] args ){
/* Understanding how to use the Stack, Flap and ScreenDockStation is easy. The first
* two are nothing else than lists, on the third the children do not influence each
* other in any way.
*
* SplitDockStation on the other hand is rather complex and you may need some training
* to put Dockables at the location you want them. This example consists of three
* methods "create...", each of them sets up a SplitDockStation in another way, but
* all of them lead to the same result.
*
* Since SplitDockStation is a Dockable itself, we can show them grouped together
* on a StackDockStation.
* */
JTutorialFrame frame = new JTutorialFrame( SplitDockStationExample.class );
DockController controller = new DockController();
controller.setRootWindow( frame );
frame.destroyOnClose( controller );
/* In order to play around we disable the automatic replacement of stations which have
* only one child. You should use this feature with care in real applications. */
controller.setSingleParentRemover( new SingleParentRemover(){
protected boolean shouldTest( DockStation station ){
if( station instanceof SplitDockStation ){
return false;
}
return super.shouldTest( station );
}
});
/* Set up some base station */
SplitDockStation station = new SplitDockStation();
controller.add( station );
frame.add( station );
StackDockStation stack = new StackDockStation();
/* We now collect the different examples. Each station contains six children, three of
* them are grouped together. In the group we would like the middle on (green) to be selected.
*
* We would also like to let the framework handle StackDockStations, we no longer
* create them explicitly.
*
* The exact layout looks like this:
*
* 40 % 60 %
* -----------------------------
* | | |
* | | Yellow | 30 %
* | Red | |
* | Green |-----------------
* | Blue | | |
* | | | |
* | | | |
* | | Cyan | Magenta | 70 %
* | | | |
* | | | |
* | | | |
* -----------------------------
* 40 % 20 % 40 %
*
*
* Have a look at the "create..." methods to understand what is going on */
stack.drop( createLayoutSequential() );
stack.drop( createLayoutTree() );
stack.drop( createLayoutGrid() );
/* Conclusion:
*
* ---------------------------------------------------------------------------------
* What Pros Cons
* ---------------------------------------------------------------------------------
* Sequential no need to add all Very hard to use
* Dockables at the same time
* ---------------------------------------------------------------------------------
* Tree Absolute control of the Not intuitive, you cannot just
* layout set a location but need to consider
* the current layout of the tree
*
* You need to build the entire layout
* at once
* ---------------------------------------------------------------------------------
* Grid Very easy, you can paint You need to build the entire layout
* your layout on a sheet of at once
* paper, measure and copy the
* position of the Dockables
* ---------------------------------------------------------------------------------
*/
/* Select the first tab */
station.drop( stack );
controller.setFocusedDockable( stack.getDockable( 0 ), false );
frame.setVisible( true );
}
/* ** Adding one Dockable after another ** */
private static SplitDockStation createLayoutSequential(){
SplitDockStation station = new SplitDockStation();
station.setTitleText("Sequential");
/* Prepare the Dockables that we are going to drop on "station" */
Dockable red = new ColorDockable( "Red", Color.RED );
Dockable green = new ColorDockable( "Green", Color.GREEN );
Dockable blue = new ColorDockable( "Blue", Color.BLUE );
Dockable yellow = new ColorDockable( "Yellow", Color.YELLOW );
Dockable cyan = new ColorDockable( "Cyan", Color.CYAN );
Dockable magenta = new ColorDockable( "Magenta", Color.MAGENTA );
/* We now drop one Dockable after the other on the station. Each time
* we call "drop" the layout of the children is changed. So we need to
* be very carefully in what we do and in the order we do it. */
/* The first Dockable does not need a location, it gets all space because
* there are no other Dockables yet. */
station.drop( red );
/* In order to group "blue" with "red" we assign the same location to "blue"
* as "red" already has */
station.drop( blue, new SplitDockProperty(0, 0, 1.0, 1.0 ));
/* We want "green" to be between "red" and "blue" and we want "green" to be selected.
* For the selection we need to add "green" last (the newest Dockable gets selected).
* We can set the position by using a "successor" position. "greenLocation" tells
* "station" that "green" is grouped with "red" and "blue", where as the StackProperty
* tells the existing StackDockStation where to put "green" */
SplitDockProperty greenLocation = new SplitDockProperty(0, 0, 1.0, 1.0 );
greenLocation.setSuccessor( new StackDockProperty( 1 ));
station.drop( green, greenLocation );
/* The group "red/green/blue" has now position 0/0/1/1 and we put "yellow" at the
* right side of this rectangle */
station.drop( yellow, new SplitDockProperty( 0.4, 0.0, 0.6, 1.0 ));
/* Now we cut of some parts of "yellow" and replace them by "cyan" */
station.drop( cyan, new SplitDockProperty( 0.4, 0.3, 0.6, 0.7 ));
/* Finally "magenta" cuts out some parts of "cyan" and replaces them */
station.drop( magenta, new SplitDockProperty( 0.6, 0.3, 0.4, 0.7 ));
return station;
}
/* ** Work with the interal structure of SplitDockStation ** */
private static SplitDockStation createLayoutTree(){
SplitDockStation station = new SplitDockStation();
station.setTitleText("Tree");
/* Prepare the Dockables we are going to put onto "station" */
Dockable red = new ColorDockable( "Red", Color.RED, 0.5f );
Dockable green = new ColorDockable( "Green", Color.GREEN, 0.5f );
Dockable blue = new ColorDockable( "Blue", Color.BLUE, 0.5f );
Dockable yellow = new ColorDockable( "Yellow", Color.YELLOW, 0.5f );
Dockable cyan = new ColorDockable( "Cyan", Color.CYAN, 0.5f );
Dockable magenta = new ColorDockable( "Magenta", Color.MAGENTA, 0.5f );
/* Internally SplitDockStation is organized as binary tree. Each node represents
* a rectangle of the station, starting with the root at 0/0/1/1. Each node
* splits its rectangle either vertically or horizontally for its two children. And
* a leaf represnts a Dockable.
*
* With the help of a SplitDockTree we can build up a tree and tell "station"
* to copy its layout from it. */
DockableSplitDockTree tree = new DockableSplitDockTree();
/* A SplitDockTree is built from bottom to top. We start by creating the group
* of "red", "green" and "blue". As you see there is a method that does exactly
* what we need to have, it even sets the selected Dockable.
* The method returns a key, this key represents the leaf we just created. */
DockableSplitDockTree.Key group = tree.put( new Dockable[]{ red, green, blue }, green );
/* We now add "cyan" and "magenta", which are neighbors, at the same time. Calling
* "tree.horizontal( tree.put( cyan ), tree.put( magenta ), 1.0/3.0" would have the
* same effect, this method is just a shortcut.
* The third parameter "1.0/3.0" tells the tree that "cyan" has the size "1/3 w" and
* "magenta" has the size "2/3 w", where "w" is the width in pixel that will be
* assigned to the node "bottomRight". */
DockableSplitDockTree.Key bottomRight = tree.horizontal( cyan, magenta, 1.0/3.0 );
/* We create a leaf for "yellow" */
DockableSplitDockTree.Key keyYellow = tree.put( yellow );
/* The "bottomRight" Dockables, cyan and magenta, are a neighbor to "yellow" which is
* at the top right. So we need to combine them vertically. */
DockableSplitDockTree.Key right = tree.vertical( keyYellow, bottomRight, 0.3 );
/* At last we have the left and the right side of our layout. We now bring them
* together. */
DockableSplitDockTree.Key root = tree.horizontal( group, right, 0.4 );
/* We built up the tree and are now telling "tree" which node is the root */
tree.root( root );
/* Finally we instruct "station" to change its layout such that it matches "tree" */
station.dropTree( tree );
return station;
}
/* ** Using helpful algorithms ** */
private static SplitDockStation createLayoutGrid(){
SplitDockStation station = new SplitDockStation();
station.setTitleText("Grid");
/* Prepare the Dockables we are going to put onto "station" */
Dockable red = new ColorDockable( "Red", Color.RED, 2.5f );
Dockable green = new ColorDockable( "Green", Color.GREEN, 2.5f );
Dockable blue = new ColorDockable( "Blue", Color.BLUE, 2.5f );
Dockable yellow = new ColorDockable( "Yellow", Color.YELLOW, 2.5f );
Dockable cyan = new ColorDockable( "Cyan", Color.CYAN, 2.5f );
Dockable magenta = new ColorDockable( "Magenta", Color.MAGENTA, 2.5f );
/* You already have seen two ways to setup the layout of a SplitDockStation, chances
* are you liked none of them. The SplitDockGrid makes things much easier: you
* only need to tell the grid where some Dockable should end up, the grid will
* calculate a layout of from this information. There is no need to add follow a
* particular order when creating the grid.
* */
SplitDockGrid grid = new SplitDockGrid();
/* We start by creating the group, which should be on the left side taking
* up 40% of the space. */
grid.addDockable( 0, 0, 40, 100, red, green, blue );
/* Then we ensure that in our new group "green" is selected. You may notice
* that we need to type in the location of "green" again. That is because
* the location is used as key in a map, and "0/0/40/100" now points to the
* group "red/green/blue". */
grid.setSelected( 0, 0, 40, 100, green );
/* And then we add the other Dockables at the location they should appear later */
grid.addDockable( 40, 0, 60, 30, yellow );
grid.addDockable( 40, 30, 20, 70, cyan );
grid.addDockable( 60, 30, 40, 70, magenta );
/* With "toTree" we convert "grid" into a SplitDockTree, then we can replace the
* layout of "station" with this tree. */
station.dropTree( grid.toTree() );
return station;
}
}