CodecExample.java
/**
* In this example every dockable can be closed. When the dockable is added again later,
* the dockable is docked as good as possible like it was docked before.
*
* When the application is stopped, the workspace is saved.
* When the application is restarted again, the workspace is recovered.
* The dockables and docks are showed in the same state as when they were closed.
*
* This example uses a float dock model.
* The model can be saved with a dock model encoder.
* The model can be reloaded with a dock model decoder.
*
* @author Heidi Rakels
*/
public class CodecExample extends JPanel
{
// Static fields.
public static final int FRAME_WIDTH = 600;
public static final int FRAME_HEIGHT = 450;
public static final String SOURCE = "codec_1_1.dck";
// Fields.
/** The ID for the owner window. */
private String frameId = "frame";
/** The model with the docks and dockables. */
private FloatDockModel dockModel;
// Constructors.
public CodecExample(JFrame frame)
{
super(new BorderLayout());
// Listen when the frame is closed. The workspace should be saved.
frame.addWindowListener(new WorkspaceSaver());
// Create the content components.
TextPanel textPanel1 = new TextPanel("I am window 1.");
TextPanel textPanel2 = new TextPanel("I am window 2.");
TextPanel textPanel3 = new TextPanel("I am window 3.");
TextPanel textPanel4 = new TextPanel("I am window 4.");
TextPanel textPanel5 = new TextPanel("I am window 5.");
TextPanel textPanel6 = new TextPanel("I am window 6.");
// Create the dockables around the content components.
Icon icon = new ImageIcon(getClass().getResource("/com/javadocking/resources/images/text12.gif"));
Dockable dockable1 = new DefaultDockable("Window1", textPanel1, "Window 1", icon);
Dockable dockable2 = new DefaultDockable("Window2", textPanel2, "Window 2", icon);
Dockable dockable3 = new DefaultDockable("Window3", textPanel3, "Window 3", icon);
Dockable dockable4 = new DefaultDockable("Window4", textPanel4, "Window 4", icon);
Dockable dockable5 = new DefaultDockable("Window5", textPanel5, "Window 5", icon);
Dockable dockable6 = new DefaultDockable("Window6", textPanel6, "Window 6", icon);
// Add close actions to the dockables.
dockable1 = new StateActionDockable(dockable1, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
dockable2 = new StateActionDockable(dockable2, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
dockable3 = new StateActionDockable(dockable3, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
dockable4 = new StateActionDockable(dockable4, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
dockable5 = new StateActionDockable(dockable5, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
dockable6 = new StateActionDockable(dockable6, new DefaultDockableStateActionFactory(), DockableState.statesClosed());
// Try to decode the dock model from file.
DockModelPropertiesDecoder dockModelDecoder = new DockModelPropertiesDecoder();
if (dockModelDecoder.canDecodeSource(SOURCE))
{
try
{
// Create the map with the dockables, that the decoder needs.
Map dockablesMap = new HashMap();
dockablesMap.put(dockable1.getID(), dockable1);
dockablesMap.put(dockable2.getID(), dockable2);
dockablesMap.put(dockable3.getID(), dockable3);
dockablesMap.put(dockable4.getID(), dockable4);
dockablesMap.put(dockable5.getID(), dockable5);
dockablesMap.put(dockable6.getID(), dockable6);
// Create the map with the owner windows, that the decoder needs.
Map ownersMap = new HashMap();
ownersMap.put(frameId, frame);
// Create the map with the visualizers, that the decoder needs.
Map visualizersMap = null;
// visualizersMap.put("maximizer", maximizer);
// visualizersMap.put("minimizer", minimizer);
// Decode the file.
dockModel = (FloatDockModel)dockModelDecoder.decode(SOURCE, dockablesMap, ownersMap, visualizersMap);
}
catch (FileNotFoundException fileNotFoundException){
System.out.println("Could not find the file [" + SOURCE + "] with the saved dock model.");
System.out.println("Continuing with the default dock model.");
}
catch (IOException ioException){
System.out.println("Could not decode a dock model: [" + ioException + "].");
ioException.printStackTrace();
System.out.println("Continuing with the default dock model.");
}
}
// These are the root docks.
SplitDock splitDock = null;
if (dockModel == null)
{
// Create the dock model for the docks because they could not be retrieved from a file.
dockModel = new FloatDockModel(SOURCE);
dockModel.addOwner(frameId, frame);
// Give the dock model to the docking manager.
DockingManager.setDockModel(dockModel);
// Create the child tab docks.
TabDock leftTabDock = new TabDock();
TabDock rightTabDock = new TabDock();
// Add the dockables to the tab dock.
leftTabDock.addDockable(dockable1, new Position(0));
leftTabDock.addDockable(dockable2, new Position(1));
rightTabDock.addDockable(dockable3, new Position(0));
rightTabDock.addDockable(dockable4, new Position(1));
// Create the split dock.
splitDock = new SplitDock();
// Add the child docks to the split dock at the left and right.
splitDock.addChildDock(leftTabDock, new Position(Position.LEFT));
splitDock.addChildDock(rightTabDock, new Position(Position.RIGHT));
splitDock.setDividerLocation(290);
// Add the root dock to the dock model.
dockModel.addRootDock("splitDock", splitDock, frame);
// Add the paths of the docked dockables to the model with the docking paths.
addDockingPath(dockable1);
addDockingPath(dockable2);
addDockingPath(dockable3);
addDockingPath(dockable4);
// Add the path of the dockables that are not docked already.
// We want dockable 5 to be docked, when it is made visible, where dockable 1 is docked.
DockingPath dockingPathToCopy1 = DockingManager.getDockingPathModel().getDockingPath(dockable1.getID());
DockingPath dockingPath5 = DefaultDockingPath.copyDockingPath(dockable5, dockingPathToCopy1);
DockingManager.getDockingPathModel().add(dockingPath5);
// We want dockable 6 to be docked, when it is made visible, where dockable 3 is docked.
DockingPath dockingPathToCopy3 = DockingManager.getDockingPathModel().getDockingPath(dockable3.getID());
DockingPath dockingPath6 = DefaultDockingPath.copyDockingPath(dockable6, dockingPathToCopy3);
DockingManager.getDockingPathModel().add(dockingPath6);
}
else
{
// Get the root dock from the dock model.
splitDock = (SplitDock)dockModel.getRootDock("splitDock");
}
// Add the root dock to the panel.
add(splitDock, BorderLayout.CENTER);
// Create the menubar.
Dockable[] dockables = new Dockable[6];
dockables[0] = dockable1;
dockables[1] = dockable2;
dockables[2] = dockable3;
dockables[3] = dockable4;
dockables[4] = dockable5;
dockables[5] = dockable6;
JMenuBar menuBar = createMenu(dockables);
frame.setJMenuBar(menuBar);
}
/**
* Creates the menubar with two menus: File and Window.
* File has the Exit menu item. Window has check boxes for the dockables.
*
* @param dockables The dockables for which a menu item has to be created.
* @return The created menu bar.
*/
private JMenuBar createMenu(Dockable[] dockables)
{
// Create the menu bar.
JMenuBar menuBar = new JMenuBar();
// Build the File menu.
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
fileMenu.getAccessibleContext().setAccessibleDescription("The file menu");
menuBar.add(fileMenu);
// Build the Window menu.
JMenu windowMenu = new JMenu("Window");
windowMenu.setMnemonic(KeyEvent.VK_W);
windowMenu.getAccessibleContext().setAccessibleDescription("The window menu");
menuBar.add(windowMenu);
// The JMenuItem for File
JMenuItem menuItem = new JMenuItem("Exit", KeyEvent.VK_E);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Exit te application");
menuItem.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
saveWorkspace();
System.exit(0);
}
});
fileMenu.add(menuItem);
// Iterate over the dockables.
for (int index = 0; index < dockables.length; index++)
{
// Create the check box menu for the dockable.
JCheckBoxMenuItem cbMenuItem = new DockableMenuItem(dockables[index]);
windowMenu.add(cbMenuItem);
}
return menuBar;
}
/**
* Creates a docking path for the dockable. This path is added to the docking pah model of the docking
* manager.
* To create a docking path, the dock model should already be given to the docking manager.
*
* @param dockable The dockable for which to create a docking path.
* @return The created docking path.
*/
private DockingPath addDockingPath(Dockable dockable)
{
if (dockable.getDock() != null)
{
// Create the docking path of the dockable.
DockingPath dockingPath = DefaultDockingPath.createDockingPath(dockable);
DockingManager.getDockingPathModel().add(dockingPath);
return dockingPath;
}
return null;
}
private void saveWorkspace()
{
// Save the dock model.
DockModelPropertiesEncoder encoder = new DockModelPropertiesEncoder();
if (encoder.canSave(dockModel))
{
try
{
encoder.save(dockModel);
}
catch (Exception e)
{
System.out.println("Error while saving the dock model.");
e.printStackTrace();
}
}
else
{
System.out.println("Could not save the dock model.");
}
}
/**
* A listener for window closing events. Saves the workspace, when the application window is closed.
*
* @author Heidi Rakels.
*/
private class WorkspaceSaver implements WindowListener
{
public void windowClosing(WindowEvent windowEvent)
{
saveWorkspace();
}
public void windowDeactivated(WindowEvent windowEvent) {}
public void windowDeiconified(WindowEvent windowEvent) {}
public void windowIconified(WindowEvent windowEvent) {}
public void windowOpened(WindowEvent windowEvent) {}
public void windowActivated(WindowEvent windowEvent) {}
public void windowClosed(WindowEvent windowEvent) {}
}
/**
* A check box menu item to add or remove the dockable.
*/
private class DockableMenuItem extends JCheckBoxMenuItem
{
public DockableMenuItem(Dockable dockable)
{
super(dockable.getTitle(), dockable.getIcon());
setSelected(dockable.getDock() != null);
DockableMediator dockableMediator = new DockableMediator(dockable, this);
dockable.addDockingListener(dockableMediator);
addItemListener(dockableMediator);
}
}
/**
* A listener that listens when menu items with dockables are selected and deselected.
* It also listens when dockables are closed or docked.
*/
private class DockableMediator implements ItemListener, DockingListener
{
private Dockable dockable;
private Action closeAction;
private Action restoreAction;
private JMenuItem dockableMenuItem;
public DockableMediator(Dockable dockable, JMenuItem dockableMenuItem)
{
this.dockable = dockable;
this.dockableMenuItem = dockableMenuItem;
closeAction = new DockableStateAction(dockable, DockableState.CLOSED);
restoreAction = new DockableStateAction(dockable, DockableState.NORMAL);
}
public void itemStateChanged(ItemEvent itemEvent)
{
dockable.removeDockingListener(this);
if (itemEvent.getStateChange() == ItemEvent.DESELECTED)
{
// Close the dockable.
closeAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Close"));
}
else
{
// Restore the dockable.
restoreAction.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Restore"));
}
dockable.addDockingListener(this);
}
public void dockingChanged(DockingEvent dockingEvent) {
if (dockingEvent.getDestinationDock() != null)
{
dockableMenuItem.removeItemListener(this);
dockableMenuItem.setSelected(true);
dockableMenuItem.addItemListener(this);
}
else
{
dockableMenuItem.removeItemListener(this);
dockableMenuItem.setSelected(false);
dockableMenuItem.addItemListener(this);
}
}
public void dockingWillChange(DockingEvent dockingEvent) {}
}
/**
* This is the class for the content.
*/
private class TextPanel extends JPanel implements DraggableContent
{
private JLabel label;
public TextPanel(String text)
{
super(new FlowLayout());
// The panel.
setMinimumSize(new Dimension(80,80));
setPreferredSize(new Dimension(150,150));
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder(Color.lightGray));
// The label.
label = new JLabel(text);
label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
add(label);
}
// Implementations of DraggableContent.
public void addDragListener(DragListener dragListener)
{
addMouseListener(dragListener);
addMouseMotionListener(dragListener);
label.addMouseListener(dragListener);
label.addMouseMotionListener(dragListener);
}
}
// Main method.
public static void createAndShowGUI()
{
// Create the frame.
JFrame frame = new JFrame("Encoder and Decoder");
// Create the panel and add it to the frame.
CodecExample panel = new CodecExample(frame);
frame.getContentPane().add(panel);
// Set the frame properties and show it.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
frame.setLocation((screenSize.width - FRAME_WIDTH) / 2, (screenSize.height - FRAME_HEIGHT) / 2);
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setVisible(true);
}
public static void main(String args[])
{
Runnable doCreateAndShowGUI = new Runnable()
{
public void run()
{
createAndShowGUI();
}
};
SwingUtilities.invokeLater(doCreateAndShowGUI);
}
}