No need for apologizes. Do you know how many Dockables there are in advance? That would make things much easier. Anyway, I put up a test application, to show you how you could set placeholders and use them. Does that get close to your needs?
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.MissingCDockableStrategy;
import bibliothek.gui.dock.common.MultipleCDockableFactory;
import bibliothek.gui.dock.common.MultipleCDockableLayout;
import bibliothek.gui.dock.common.SingleCDockable;
import bibliothek.gui.dock.common.event.CVetoClosingEvent;
import bibliothek.gui.dock.common.event.CVetoClosingListener;
import bibliothek.gui.dock.common.perspective.CControlPerspective;
import bibliothek.gui.dock.common.perspective.CGridPerspective;
import bibliothek.gui.dock.common.perspective.CPerspective;
import bibliothek.gui.dock.common.perspective.SingleCDockablePerspective;
public class SegmentTest {
public static void main( String[] args ){
JFrame frame = new JFrame();
CControl control = new CControl( frame );
// define a rule telling which placeholders should never be automatically removed
control.setMissingStrategy( new MissingCDockableStrategy(){
@Override
public boolean shouldStoreSingle( String id ){
// mark our placeholders, make sure they are not automatically deleted
return "topleft".equals( id ) || "topright".equals( id ) || "bottomleft".equals( id ) || "bottomright".equals( id );
}
@Override
public boolean shouldStoreMulti( String id ){
// not called in this example
return false;
}
@Override
public <L extends MultipleCDockableLayout> boolean shouldCreate( String id, MultipleCDockableFactory<?, L> factory, String uniqueId, L data ){
// not called in this example
return false;
}
@Override
public boolean shouldCreate( String id, MultipleCDockableFactory<?, ?> factory ){
// not called in this example
return false;
}
} );
// build up a seemingly empty grid, first initialize the
control.getContentArea();
buildPerspective( control );
frame.add( control.getContentArea() );
frame.setBounds( 20, 20, 400, 400 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
JFrame buttons = new JFrame( "Buttons" );
buttons.setLayout( new GridLayout( 2, 2 ) );
buttons.add( createButton( control, "topleft", "TL" ) );
buttons.add( createButton( control, "topright", "TR" ) );
buttons.add( createButton( control, "bottomleft", "BL" ) );
buttons.add( createButton( control, "bottomright", "BR" ) );
buttons.setBounds( 420, 20, 200, 200 );
frame.setVisible( true );
buttons.setVisible( true );
}
private static void buildPerspective( CControl control ){
CControlPerspective perspectives = control.getPerspectives();
CPerspective perspective = perspectives.createEmptyPerspective();
CGridPerspective center = perspective.getContentArea().getCenter();
// add dummy dockables to store the location
center.gridAdd( 0, 0, 25, 25, new SingleCDockablePerspective( "topleft" ) );
center.gridAdd( 0, 25, 25, 75, new SingleCDockablePerspective( "bottomleft" ) );
center.gridAdd( 25, 0, 75, 60, new SingleCDockablePerspective( "topright" ) );
center.gridAdd( 25, 60, 75, 40, new SingleCDockablePerspective( "bottomright" ) );
// add the placeholders that need to remain
center.gridPlaceholder( 0, 0, 25, 25, new SingleCDockablePerspective( "topleft" ) );
center.gridPlaceholder( 0, 25, 25, 75, new SingleCDockablePerspective( "bottomleft" ) );
center.gridPlaceholder( 25, 0, 75, 60, new SingleCDockablePerspective( "topright" ) );
center.gridPlaceholder( 25, 60, 75, 40, new SingleCDockablePerspective( "bottomright" ) );
// apply the new layout
center.gridDeploy();
perspective.storeLocations();
perspectives.setPerspective( perspective, true );
}
private static JButton createButton( final CControl control, final String id, final String text ){
JButton button = new JButton( text );
button.addActionListener( new ActionListener(){
@Override
public void actionPerformed( ActionEvent e ){
SingleCDockable initial = control.getSingleDockable( id );
final DefaultSingleCDockable dockable;
// If there is not yet a dockable for "id" we can now just create it and add it ...
if( initial == null ){
dockable = new DefaultSingleCDockable( id, text );
dockable.setCloseable( true );
control.addDockable( dockable );
dockable.setVisible( true );
}
else{
// .. but if there is one we search a new unique id and add a new dockable close to
// the existing one.
int index = 0;
while( control.getSingleDockable( id + index ) != null ){
index++;
}
dockable = new DefaultSingleCDockable( id + index, text + " " + index );
dockable.setCloseable( true );
control.addDockable( dockable );
dockable.setLocation( initial.getBaseLocation().aside() );
dockable.setVisible( true );
}
// And we should clean up any dockable we no longer need
dockable.addVetoClosingListener( new CVetoClosingListener(){
@Override
public void closing( CVetoClosingEvent event ){
// ignore
}
@Override
public void closed( CVetoClosingEvent event ){
control.removeDockable( dockable );
}
} );
}
} );
return button;
}
}