Hi, I am having a mainframe which has multiple DefaultSingleCDockable docks and using one CCControl. I used your EnvironmentDockable as one of the dockable in the main window. Now using dock action I moving dockables in the mainwindow into the EnvironmentDockable dock. When I move the dockable from main frame into this EnvironmentDockable I am doing the following

DefaultSingleCDockable target;

I am able to do all these. Now when I close the main window/frame, I am saving the perspective in two files. When I restart, I am able to load the xml for mainframe and also for the EnvironmentDockable perspective and that’s loading but I am not seeing any dockable at all in the other EnvironmentDockable. The xml that’s saved has all the details and I didn’t see any errors.

I believe the problem could be with the way I am loading the dockables in the mainframe and they all gets added to the mainframe CControl. I am not sure how I can overcome this and load both, could you please advise if there is any option in the framework?

A CDockable can be registered at only one CControl. An idea could be to register a SingleCDockableFactory at both CControls (see „CControl.addSingleDockableFactory(…)“). The first CControl which wants to show the Dockable would call the factory, and then you could return your dockable. And if a CControl does not want to show a Dockable, then the factory is never called.

… this is just a theory, I guess it should work, but testing the theory would be a good idea :wink:

Thanks for the reply Beni. But even if I use the factory in both the control I have to first load the layout to figure out the dockables that are moved to this external EnvDockable right. The loading of perspective is the last step in my mainframe screen as of now, so I need find a way.

Is there a different option for my requirement, like I saw ScreenDockStation. Can you point me to any examples where I can try if that can be used, also I am not sure if I can save the Screendockstation docks with the same mainframe perspective. Please let me know

actually you can see my screen in my other post …

Hm, perhaps I did not correctly understand your problem.

Have you had a look at the class “MultiFrameExample”? It is in the tutorial-project, and it shows how the framework deals with an application that has more than one JFrame. Perhaps that is a solution to your problem?

Because using multiple CControls and switching Dockables seems a bit bogus.

My requirement was more like in this thread

But I am not able to access this class CMaximizeBehavior. I am using this version 1.1.1.

Also I am having problem using this , it says couldn’t match type arguments
CStation screen = (CStation) control.getStation( CControl.EXTERNALIZED_STATION_ID );

One more help. We are not allowing all users to rearrange the windows, I know you don’t like that but the client’s requirement is to avoid confusion with all the users incase if they close the window. The tool is mostly used by CSR. Here is what I am seeing when I use the above approach, as an admin I moving the windows out and docking as a second screen and saving the perspective. To avoid user changing the window size or moving it I used the ScreenDockWindowConfiguration as you suggested in my previous post. So as an admin I am seeing the second screen appearing with the same screen dimension when I close and open my tool.

But when a non admin user selects the same perspective, the second window size for some reason is getting stretched more than what I set. In the window config i am setting the below properties


Regarding the other thread: CMaximizedBehavior has been replaced by CGroupBehavior. The code in the other thread should now look like this:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

import bibliothek.gui.DockController;
import bibliothek.gui.DockStation;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.ScreenDockStation;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.action.ListeningDockAction;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.action.CPanelPopup;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.CommonDockable;
import bibliothek.gui.dock.common.intern.station.CScreenDockStation;
import bibliothek.gui.dock.common.intern.ui.CSingleParentRemover;
import bibliothek.gui.dock.common.mode.ExtendedMode;
import bibliothek.gui.dock.event.DockStationAdapter;
import bibliothek.gui.dock.facile.mode.LocationMode;
import bibliothek.gui.dock.facile.mode.LocationModeManager;
import bibliothek.gui.dock.station.split.SplitDockStationFactory;

public class Test {
	public static void main( String[] args ){
		// setting up frame and controller
		JFrame frame = new JFrame();
		CControl control = new CControl( frame );
		// control.setMaximizeBehavior( new CustomCMaximizeBehavior() );
		control.setGroupBehavior( new CustomCGroupBehavior() );
		// if we ever want to work with layouts, we have install a factory for our specialized SplitDockStation
		control.intern().registerFactory( new CustomSplitDockStationFactory() );
		// now access the DockStation which shows our detached (externalized) items
		CStation<CScreenDockStation> screen = (CStation<CScreenDockStation>) control.getStation( CControl.EXTERNALIZED_STATION_ID );

		// if a Dockable is added to that station... 
		screen.getStation().addDockStationListener( new DockStationAdapter(){
			public void dockableAdded( DockStation station, Dockable dockable ){
				// ... and the new child is not a SplitDockStation ...
				if( !(dockable instanceof SplitDockStation )){
					// .. then we just insert a SplitDockStation
					SplitDockStation split = new CustomSplitDockStation( false );
					DockController controller = station.getController();
						// disable events while rearanging our layout
						station.replace( dockable, split );
						split.drop( dockable );
						// and enable events after we finished
		// make sure a SplitDockStation with one child and a parent that is a ScreenDockStation does not get removed
		control.intern().getController().setSingleParentRemover( new CSingleParentRemover( control ){
			protected boolean shouldTest( DockStation station ){
				if( station instanceof SplitDockStation ){
					SplitDockStation split = (SplitDockStation)station;
					if( split.getDockParent() instanceof ScreenDockStation ){
						// but we want to remove the station if it does not have any children at all
						return split.getDockableCount() == 0;
				return super.shouldTest( station );

		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setSize( 700, 700 );

		DefaultSingleCDockable red = create( control, "Red", Color.RED );
		DefaultSingleCDockable green = create( control, "Green", Color.GREEN );
		DefaultSingleCDockable blue = create( control, "Blue", Color.BLUE );

		CGrid grid = new CGrid( control );
		grid.add( 0, 0, 10, 10, red );
		grid.add( 10, 0, 5, 5, green );
		grid.add( 10, 5, 5, 5, blue );

		control.getContentArea().deploy( grid );
		frame.getContentPane().add( control.getContentArea(), BorderLayout.CENTER );
		frame.setSize( new Dimension( 600, 600 ) );
		frame.setVisible( true );

	public static DefaultSingleCDockable create( CControl control, String title, Color color ){
		JPanel panel = new JPanel();
		panel.setOpaque( true );
		panel.setBackground( color );

		final DefaultSingleCDockable singleDockable = new DefaultSingleCDockable( title, title, panel );

		CPanelPopup popup = new CPanelPopup();
		JButton button = new JButton( "Button" );
		button.setPreferredSize( new Dimension( 400, 300 ) );
		popup.setContent( button );

		singleDockable.addAction( popup );

		return singleDockable;
	// we write a custom factory for our SplitDockStation
	private static class CustomSplitDockStationFactory extends SplitDockStationFactory{
		public static final String ID = "custom split dock station";
		protected SplitDockStation createStation( boolean hasFullscreenAction ){
			return new CustomSplitDockStation( hasFullscreenAction );
		public String getID(){
			return ID;
	// we use a custom type for the SplitDockStation, in this case the station will not show
	// a fullscreen-action
	private static class CustomSplitDockStation extends SplitDockStation{
		public CustomSplitDockStation( boolean hasFullscreenAction ){
			super( hasFullscreenAction );
		public String getFactoryID(){
			return CustomSplitDockStationFactory.ID;
		protected ListeningDockAction createFullScreenAction(){
			return null;

	// maximization of a floating SplitDockStation: this behavior will maximize the station too
	private static class CustomCGroupBehavior extends StackGroupBehavior {
		public Dockable getGroupElement( LocationModeManager<? extends LocationMode> manager, Dockable dockable, ExtendedMode mode ){
			DockStation parent = dockable.getDockParent();
			if( parent instanceof StackDockStation || (parent instanceof SplitDockStation && parent.asDockable().getDockParent() instanceof ScreenDockStation) ) {
				Dockable result = getMaximizingElement( parent, dockable );
				if( result != dockable ){
					return result;
			return super.getGroupElement( manager, dockable, mode );
		public Dockable getMaximizingElement( DockStation parent, Dockable dockable ){
			for( int i = 0, n = parent.getDockableCount(); i < n; i++ ) {
				Dockable check = parent.getDockable( i );
				if( check != dockable ) {
					if( check instanceof CommonDockable ) {
						CDockable fdock = ((CommonDockable) check).getDockable();
						if( !fdock.isMaximizable() )
							return dockable;
			return parent.asDockable();

... but I have no clue if that helps you...