Add a custom action in a CGridArea

Hello !

I would like to add a action (CAction) in a CGridArea that’s is Stackable.
Is it possible ? If yes, how ?

Thanks for your reply !!!

Gilles

This is a bit tricky, you cannot add the actions directly, but there is a mechanism to add actions indirectly to any Dockable. This mechanism is based on the interface “ActionGuard” and an example is shown below.

The reason why CGridAreas do not support actions directly is because they rarely need them, and because they usually do not have any place where the actions are shown to the user.


import javax.swing.JFrame;

import bibliothek.gui.Dockable;
import bibliothek.gui.dock.action.ActionGuard;
import bibliothek.gui.dock.action.DefaultDockActionSource;
import bibliothek.gui.dock.action.DockActionSource;
import bibliothek.gui.dock.action.LocationHint;
import bibliothek.gui.dock.common.CControl;
import bibliothek.gui.dock.common.CGridArea;
import bibliothek.gui.dock.common.CStation;
import bibliothek.gui.dock.common.action.CAction;
import bibliothek.gui.dock.common.action.CButton;
import bibliothek.gui.dock.common.intern.CommonDockable;

public class Actions {
	public static void main(String[] args) {
		// building the application ...
		JFrame frame = new JFrame();
		CControl control = new CControl(frame);
		
		// we create a custom ActionGuard which adds new actions to all CGridAreas
		ActionGuard guard = new GridGuard(new CButton("Hello", null), new CButton("Bye bye", null));
		control.getController().addActionGuard(guard);
		
		// ... continue building the application here
		
		frame.add(control.getContentArea());
		
		CGridArea area = new CGridArea(control, "grid"){
			@Override
			public boolean isTitleShown() {
				return true;
			}
		};
		control.addStation(area, true);
		control.addDockable(area);
		area.setVisible(true);
		
		frame.setBounds(20, 20, 400, 400);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setVisible(true);
	}
	
	// An ActionGuard allows you to add DockActions to any Dockable
	private static class GridGuard implements ActionGuard{
		private DockActionSource source;
		
		public GridGuard( CAction... actions ){
			// We build a default source. You can modify this source (add/remove actions) at any time.
			DefaultDockActionSource source = new DefaultDockActionSource(new LocationHint(LocationHint.ACTION_GUARD, LocationHint.MIDDLE));
			for( CAction action : actions ){
				source.add( action.intern() );
			}
			this.source = source;
		}
		
		@Override
		public boolean react(Dockable dockable) {
			// You need to find out, whether "dockable" is the CGridArea that should have the actions
			// If you subclass CGridArea you can check with "instanceof MyCGridArea".
			// If you know the object you could use the "==" operator
			
			if( dockable instanceof CommonDockable ){
				CommonDockable cdockable = (CommonDockable)dockable;
				CStation<?> station = cdockable.getDockable().asStation();
				if( station instanceof CGridArea ){
					return true;
				}
			}
			return false;
		}
		
		@Override
		public DockActionSource getSource(Dockable dockable) {
			// It does not matter how you get to a DockActionSource. You
			// can create a new one, you can somehow read if from "dockable" (e.g. if it is 
			// a subclass of CGridArea with a new field), you can reuse the same source
			// over and over again (like in this example)
			return source;
		}
	}
}

Thanks ! Beni

That’s exactly what I looking for !!! :slight_smile: