CWorkingArea

Thank you :slight_smile:

I’ll be waiting for your skeleton.

I need to detached, full screen, minimized, maximized, etc… each dockables inside the future CStation that wrapps around a StackDockStation. Is this feasible also?

Thank you

Ok, here is the example. I needed to tweak the framework a tiny bit (there was a collision of two methods with the same name in two different interfaces), so this will only work with 1.1.0p6e, which I’ll upload within the next few hours.


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;

import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;
import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.CMinimizeArea;
import bibliothek.gui.dock.common.event.CDockableLocationEvent;
import bibliothek.gui.dock.common.event.CDockableLocationListener;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.intern.AbstractCStation;
import bibliothek.gui.dock.common.intern.CControlAccess;
import bibliothek.gui.dock.common.intern.DefaultCDockable;
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;

public class StationExample {
	/* This example shows how a StackDockStation is converted into a CStation and how that
	 * CStation is registered as a station for dockable in the "normal" mode.
	 * 
	 * 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( StationExample.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 );
		
		/* We create our stack and some other CStations... */
		CStack stack = new CStack( "stack" );
		control.addStation( stack, true );
		
		CMinimizeArea east = control.createMinimizeArea( "east" );
		CMinimizeArea west = control.createMinimizeArea( "west" );
		CMinimizeArea south = control.createMinimizeArea( "south" );
		CMinimizeArea north = control.createMinimizeArea( "north" );
		
		/* ... and add them to our JFrame */
		frame.add( stack.getStation().getComponent() );
		frame.add( east, BorderLayout.EAST );
		frame.add( west, BorderLayout.WEST );
		frame.add( south, BorderLayout.SOUTH );
		frame.add( north, BorderLayout.NORTH );
		
		/* Now we set up some Dockable to play around with */
		final ColorSingleCDockable red = new ColorSingleCDockable( "Red", Color.RED );
		final ColorSingleCDockable green = new ColorSingleCDockable( "Green", Color.GREEN );
		final ColorSingleCDockable blue = new ColorSingleCDockable( "Blue", Color.BLUE );
		
		control.addDockable( red );
		control.addDockable( green );
		control.addDockable( blue );
		
		/* We fall back to the Core API to make the Dockables visible */
		stack.getStation().add( red.intern(), 0 );
		stack.getStation().add( green.intern(), 1 );
		stack.getStation().add( blue.intern(), 2 );
		
		frame.setVisible( true );
		
		EventQueue.invokeLater( new Runnable(){
			public void run(){
				/* We enabled or disable "maximized" mode depending on the current mode
				 * of the Dockables. */
				setup( red );
				setup( green );
				setup( blue );	
			}
		});
	}
	
	private static void setup( final DefaultCDockable dockable ){
		dockable.setMaximizable( false );
		dockable.addCDockableLocationListener( new CDockableLocationListener(){
			public void changed( CDockableLocationEvent event ){
				ExtendedMode mode = dockable.getExtendedMode();
				dockable.setMaximizable( mode == ExtendedMode.EXTERNALIZED || mode == ExtendedMode.MAXIMIZED );
			}
		});
	}
	
	/* 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. */
	private static class CStack extends AbstractCStation<StackDockStation> implements CNormalModeArea{
		public CStack( String id ){
			StackDockStation station = new StackDockStation();
			
			/* Initialization, the CLocation points to 'station'. */
			init( station, id, 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;
				}
			});
		}

		/* 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(){
			throw new IllegalStateException( "not implemented" );
		}

		public CLocation getBaseLocation(){
			return getStationLocation();
		}

		public boolean isNormalModeChild( Dockable dockable ){
			return isChild( dockable );
		}

		public DockableProperty getLocation( Dockable child ){
			return DockUtilities.getPropertyChain( getStation(), child );
		}

		public void setLocation( Dockable dockable, DockableProperty location, AffectedSet set ){
			set.add( dockable );
			
			if( isChild( dockable )){
				getStation().move( dockable, location );
			}
			else{
				if( !getStation().drop( dockable, location )){
					getStation().drop( dockable );
				}
			}
		}

		public void addModeAreaListener( ModeAreaListener listener ){
			// not required
		}

		public boolean autoDefaultArea(){
			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( property );
		}

		public CLocation getCLocation( Dockable dockable, Location location ){
			DockableProperty property = location.getLocation();
			if( property == null ){
				return getStationLocation();
			}
			
			return getStationLocation().expandProperty( property );
		}

		public boolean respectWorkingAreas(){
			return true;
		}
	}
}

Thank you Beni. This is great :slight_smile:

One of my cases is to add the CStack to a CWorkingArea, I got an null pointer exception because the CStack.asDockable() is returning null (since it is not implemented). I tried to implement the asDockable() method, so I’ll have to let the CStak implement CommonDockable…
I don’t know if I’m on the right way

Exception in thread „main“ java.lang.NullPointerException
at bibliothek.gui.dock.common.CGrid.add(CGrid.java:124)
at tutorial.common.basics.M_StationExample.main(M_StationExample.java:64)


import java.awt.Color;
import java.awt.EventQueue;

import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;
import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.StackDockStation;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.CLocation;
import bibliothek.gui.dock.common.event.CDockableLocationEvent;
import bibliothek.gui.dock.common.event.CDockableLocationListener;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.intern.AbstractCStation;
import bibliothek.gui.dock.common.intern.CControlAccess;
import bibliothek.gui.dock.common.intern.CDockable;
import bibliothek.gui.dock.common.intern.DefaultCDockable;
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;

public class M_StationExample {
	/* This example shows how a StackDockStation is converted into a CStation and how that
	 * CStation is registered as a station for dockable in the "normal" mode.
	 * 
	 * 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( M_StationExample.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 );
		
		/* We create our stack and some other CStations... */
		CStack stack = new CStack( "stack" );
		
		/* Now we set up some Dockable to play around with */
		final ColorSingleCDockable red = new ColorSingleCDockable( "Red", Color.RED );
		final ColorSingleCDockable green = new ColorSingleCDockable( "Green", Color.GREEN );
		final ColorSingleCDockable blue = new ColorSingleCDockable( "Blue", Color.BLUE );
		
		control.addDockable( red );
		control.addDockable( green );
		control.addDockable( blue );
		
		/* We fall back to the Core API to make the Dockables visible */
		stack.getStation().add( red.intern(), 0 );
		stack.getStation().add( green.intern(), 1 );
		stack.getStation().add( blue.intern(), 2 );
		
        CGrid grid = new CGrid(control);
        grid.add(0, 0, 10, 10, new ColorSingleCDockable("blue", Color.BLUE));
        grid.add(0, 10, 10, 10, stack.asDockable());
        control.getContentArea().deploy(grid);
        
        frame.getContentPane().add(control.getContentArea());
        
		frame.setVisible( true );
		
		EventQueue.invokeLater( new Runnable(){
			public void run(){
				/* We enabled or disable "maximized" mode depending on the current mode
				 * of the Dockables. */
				setup( red );
				setup( green );
				setup( blue );	
			}
		});
	}
	

	private static void setup( final DefaultCDockable dockable ){
		dockable.setMaximizable( false );
		dockable.addCDockableLocationListener( new CDockableLocationListener(){
			public void changed( CDockableLocationEvent event ){
				ExtendedMode mode = dockable.getExtendedMode();
				dockable.setMaximizable( mode == ExtendedMode.EXTERNALIZED || mode == ExtendedMode.MAXIMIZED );
			}
		});
	}
	
	/* 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. */
	private static class CStack extends AbstractCStation<StackDockStation> implements CNormalModeArea{
		public CStack( String id ){
			StackDockStation station = new StackDockStation();
			
			/* Initialization, the CLocation points to 'station'. */
			init( station, id, 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;
				}
			});
		}

		/* 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(){
			throw new IllegalStateException( "not implemented" );
		}

		public CLocation getBaseLocation(){
			return getStationLocation();
		}

		public boolean isNormalModeChild( Dockable dockable ){
			return isChild( dockable );
		}

		public DockableProperty getLocation( Dockable child ){
			return DockUtilities.getPropertyChain( getStation(), child );
		}

		public void setLocation( Dockable dockable, DockableProperty location, AffectedSet set ){
			set.add( dockable );
			
			if( isChild( dockable )){
				getStation().move( dockable, location );
			}
			else{
				if( !getStation().drop( dockable, location )){
					getStation().drop( dockable );
				}
			}
		}

		public void addModeAreaListener( ModeAreaListener listener ){
			// not required
		}

		public boolean autoDefaultArea(){
			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( property );
		}

		public CLocation getCLocation( Dockable dockable, Location location ){
			DockableProperty property = location.getLocation();
			if( property == null ){
				return getStationLocation();
			}
			
			return getStationLocation().expandProperty( property );
		}

		public boolean respectWorkingAreas(){
			return true;
		}
		
	}
}

Could you please advice?

Thank you

Small correction .

I tried to implement the asDockable() method, so I’ll have to let the CStak implement CommonStation…

The interface CommonDockable must be implemented by a subclass of StackDockStation. I currently have some high priority stuff to do at work, but you should have a look at the existing stations to see how it could be done. I can a have a closer look at all of this in the evening.

Hi,

I look at the CSplitDockStation…

I tried to make the CStack implements CommonStation

private static class CStack extends AbstractCStation implements CNormalModeArea, CommonStation {

and I’m getting the following error :

The return types are incompatible for the inherited methods

  1. ModeArea.getStation(),
  2. CommonDockable.getStation(),
  3. AbstractCStation.getStation()

So I’ll be waiting for your closer look of this in the evening

Thank you

Hi,

Any suggestion?

Thank you

Sorry, I was kind of distracted yesterday. Currently working on the problem.

And here it is. That should work almost exactly like a CWorkingArea.


import java.awt.Color;

import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;
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.station.CommonStation;
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;

public class StationExample {
	/* 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( StationExample.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<StackDockStation> 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 void setLocation( Dockable dockable, DockableProperty location, AffectedSet set ){
			set.add( dockable );
			
			if( isChild( dockable )){
				getStation().move( dockable, location );
			}
			else{
				if( !getStation().drop( dockable, location )){
					getStation().drop( dockable );
				}
			}
		}

		public void addModeAreaListener( ModeAreaListener listener ){
			// not required
		}

		public boolean autoDefaultArea(){
			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( property );
		}

		public CLocation getCLocation( Dockable dockable, Location location ){
			DockableProperty property = location.getLocation();
			if( property == null ){
				return getStationLocation();
			}
			
			return getStationLocation().expandProperty( 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 CommonStation<StackDockStation>{
		private CStack delegate;
		
		public CStackDockStation( CStack stack ){
			this.delegate = stack;
		}
		
		public CDockable getDockable(){
			return delegate;
		}

		public DockActionSource[] getSources(){
			return delegate.getSources();
		}

		public CStation<StackDockStation> getStation(){
			return delegate;
		}
		
		@Override
		public StackDockStation asDockStation(){
			return this;
		}
	}
}

Hi,

Thank you so much Beni.
I applied the eclipse theme and did some customization, I need in the stack component, to remove [the second title]. If you run the example you’ll notice that, their 2 white dockable title description, and it is minimizable, maximizable, detachable from 2 places. I’m trying to remove this visual duplication.
Could you please advice?

Attached is the current result and the expected images

Below is the updated code:


import java.awt.Color;

import javax.swing.border.Border;

import bibliothek.extension.gui.dock.theme.EclipseTheme;
import bibliothek.extension.gui.dock.theme.eclipse.stack.EclipseTabPane;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.BorderedComponent;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.InvisibleTab;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.InvisibleTabPane;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.RectGradientPainter;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.TabComponent;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.TabPainter;
import bibliothek.extension.gui.dock.theme.eclipse.stack.tab.TabPanePainter;

import bibliothek.gui.DockController;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.common.CContentArea;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGrid;
import bibliothek.gui.dock.common.group.CGroupBehavior;
import bibliothek.gui.dock.common.theme.ThemeMap;

import tutorial.support.ColorSingleCDockable;
import tutorial.support.JTutorialFrame;


public class StationExampleFinal {
    /* 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 StationExampleFinal() {
    }


    public static void main(String[] args) {
        /* Setting up a frame */
        JTutorialFrame frame = new JTutorialFrame(StationExample.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);
        white.setCloseable(true);
        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);
        applyThemeCustomization(control, white, gray, black);
        /* 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);
    }

    private static void applyThemeCustomization(CControl control, final ColorSingleCDockable white, final ColorSingleCDockable gray, final ColorSingleCDockable black) {
        control.setTheme(ThemeMap.KEY_ECLIPSE_THEME);
        System.out.println(control.getController().getProperties().get(EclipseTheme.PAINT_ICONS_WHEN_DESELECTED));
        TabPainter painter = new TabPainter() {

            @Override
            public Border getFullBorder(BorderedComponent owner, DockController controller, Dockable dockable) {
                return RectGradientPainter.FACTORY.getFullBorder(owner, controller, dockable);
            }

            @Override
            public TabComponent createTabComponent(EclipseTabPane pane, Dockable dockable) {
                return RectGradientPainter.FACTORY.createTabComponent(pane, dockable);
            }

            @Override
            public InvisibleTab createInvisibleTab(InvisibleTabPane pane, Dockable dockable) {
                return RectGradientPainter.FACTORY.createInvisibleTab(pane, dockable);
            }

            @Override
            public TabPanePainter createDecorationPainter(EclipseTabPane pane) {
                return RectGradientPainter.FACTORY.createDecorationPainter(pane);
            }
        };
        control.getController().getProperties().set(EclipseTheme.TAB_PAINTER, painter);
    }
}

Hehe, that is a funny effect. I admit, I don’t have a clue why this happens. But I’m sure it’s just a small configuration error, I’ll report back in the evening.

[Edit: see also this thread]

Thank you Beni

Should work again.

Thank you Beni. It is working fine :slight_smile:

Hi,

In the above example, what should I change in order to

  1. Move one dockable from the stack and put it as split with another dockable
  2. Put back, the moved dockable to inside the stack

Thank you

I guess you are not Saba. The entire point of this example is, that exactly that is not possible. I’m not sure what you want to do but:

  • Use a normal CWorkingArea?
  • Don’t set the “working-area” property in both the stack and the dockables?

The framework will not allow you to create a SplitDockStation inside the StackDockStation by dragging a Dockable there.

Sorry Beni, the session logout automatically while writing and I didn’t notice that. I’m Saba :slight_smile:

I don’t want inside the CStack to have a split in order to be able to manage the CStatck as a component.
But because I’ve added the CStack to a CContentArea, which contains SplitDockStation, I want to only be able to move one dockable from the stack to the SplitDockStation of the CContentArea and to move it back to the CStack when needed

Another question, How can I be notified when at runtime I select a dockable from the stack, or when I remove a dockable from the stack (by closing it) or when I add a dockable to the stack (dragging it to the Stack)
Should I use this.stack.getStation().addDockStationListener(…)

Thank you

Ok.

  1. question: do not call “gray.setWorkingArea(stack);” and make sure the method “CStack.isWorkingArea()” return “false”. This will allow free movement of all the children (if the stack is made invisible by the framework, then this would be a bug of the framework). Also dockables which were not on the stack initially could be moved onto the stack, if you don’t want that you’d have to install a “DockAcceptance” at the DockController.

  2. question: The DockStationListener is certainly an option. If you want to use interfaces from Common: movement can be detected by the “CDockableLocationListener” which is added to the CDockable. And a “CFocusListener” could tell you when the user selected a Dockable.

Thank you.