Maybe just disabling the actions would be an alternative?
But there is a way to build groups. It is not necessary a “nice” way, but it works well enough. All you need to know is that actions are always grouped in “DockActionSources” (the sources build a tree), and that we can smuggle a few new sources into our Dockable. The code below will do that, notice that “addAction” or “insertAction” still works, but actions added that way will appear either on the left or the right side of our new group, never inside the group.
[Edit: there are other, more general solutions, like using an ActionGuard. But this solution here requires no set up and only one new class.]
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.Icon;
import javax.swing.JFrame;
import bibliothek.gui.dock.action.DefaultDockActionSource;
import bibliothek.gui.dock.action.LocationHint;
import bibliothek.gui.dock.action.MultiDockActionSource;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.DefaultSingleCDockable;
import bibliothek.gui.dock.common.action.CButton;
import bibliothek.gui.dock.common.intern.DefaultCommonDockable;
public class Dock26 {
public static void main( String[] args ){
/* A frame and control... */
JFrame frame = new JFrame( "Test" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setBounds( 20, 20, 300, 300 );
CControl control = new CControl( frame );
frame.add( control.getContentArea() );
/* This is our specialized SingleCDockable that offers groups for actions */
ActionCDockable dockable = new ActionCDockable( "t", "Test" );
control.addDockable( dockable );
dockable.setVisible( true );
/* We create a few actions, and tell them to which group the will belong */
ColorAction red = new ColorAction( Color.RED, dockable.redActions );
ColorAction green = new ColorAction( Color.GREEN, dockable.greenActions );
ColorAction blue = new ColorAction( Color.BLUE, dockable.blueActions );
/* We tell the groups what actions exist. Notice the call to "intern", we need to
* use API from Core to work here. */
dockable.redActions.add( red.intern() );
dockable.greenActions.add( green.intern() );
dockable.blueActions.add( blue.intern() );
frame.setVisible( true );
}
/* This is one of our grouped actions. If the user clicks on it, it adds a copy of
* itself into its group. */
private static class ColorAction extends CButton{
private Color color;
private DefaultDockActionSource group;
public ColorAction( Color color, DefaultDockActionSource group ){
setIcon( new ColorIcon( color ) );
this.color = color;
this.group = group;
}
@Override
protected void action(){
super.action();
group.add( new ColorAction( color, group ).intern() );
}
}
private static class ColorIcon implements Icon{
private Color color;
public ColorIcon( Color color ){
this.color = color;
}
@Override
public void paintIcon( Component c, Graphics g, int x, int y ){
g.setColor( color );
g.fillOval( x, y, 16, 16 );
}
@Override
public int getIconWidth(){
return 16;
}
@Override
public int getIconHeight(){
return 16;
}
}
/* Our specialed SingleCDockable... */
public static class ActionCDockable extends DefaultSingleCDockable{
/* ... has an additional "DockActionSource" which represents *all* groups, a "super-group".
* We could achieve the same effects without this object, but the code is more readable with it. */
private MultiDockActionSource groupedActions;
/* These are our groups */
private DefaultDockActionSource redActions;
private DefaultDockActionSource greenActions;
private DefaultDockActionSource blueActions;
public ActionCDockable( String id, String title ){
super( id, title );
/* Each group is just a list of DockActions */
redActions = new DefaultDockActionSource();
greenActions = new DefaultDockActionSource();
blueActions = new DefaultDockActionSource();
/* And we need to tell our super-group which groups exist */
groupedActions.add( redActions );
groupedActions.add( greenActions );
groupedActions.add( blueActions );
}
@Override
protected DefaultCommonDockable createCommonDockable(){
/* As this method is called from the super constructor, we need to initalize and assign
* "groupedActions" here */
if( groupedActions == null ){
/* The LocationHint tells at which location, in respect to other actions, our groups appear */
groupedActions = new MultiDockActionSource( new LocationHint( LocationHint.LEFT ) );
}
/* Finally we execute the same code as the original "createCommonDockable", but smuggle our
* super-group into the call. */
return new DefaultCommonDockable( this, groupedActions, getClose() );
}
}
}