package tutorial.dockFrontend.basics;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.Arrays;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import tutorial.support.ColorDockable;
import tutorial.support.JTutorialFrame;
import tutorial.support.TextDockable;
import tutorial.support.Tutorial;
import bibliothek.extension.gui.dock.theme.SmoothTheme;
import bibliothek.gui.DockFrontend;
import bibliothek.gui.Dockable;
import bibliothek.gui.dock.SplitDockStation;
import bibliothek.gui.dock.event.DockFrontendAdapter;
import bibliothek.gui.dock.station.split.SplitDockGrid;
import bibliothek.gui.dock.themes.NoStackTheme;
import bibliothek.util.xml.XElement;
import bibliothek.util.xml.XIO;
@Tutorial( title="Persistent Layout", id="DFPersistentLayout" )
public class PersistentLayoutExample {
public static void main( String[] args ){
/* You already have seen how a layout can be persistently stored using
* the class DockSituation or PredefinedDockSituation. But maybe the
* user would like to store more than one layout, and maybe you don't
* like to setup a DockSituation all the times.
*
* DockFrontend offers methods to store more than one layout persistently,
* the user just has to give the different layouts a name. The methods
* responsible for handling layouts are:
*
* - write/read: writes/reads all the stored layouts and the current
* layout from/to a file.
* - save/load/delete: saves, loads or deletes a layout, each layout
* is identified by a unique String
* - setEntryLayout: if set to true, then a Dockables location gets
* stored every time "save" is called. If set to false, then
* the location gets only stored if "write" is called.
*
* This example allows you to experiment with the save/load/delete and
* shows what data is stored when you use the write/read methods. */
/* Setting up a frame, a frontend, a DockStation and some Dockables */
JTutorialFrame frame = new JTutorialFrame( PersistentLayoutExample.class );
DockFrontend frontend = new DockFrontend( frame );
frame.destroyOnClose( frontend );
frontend.getController().setTheme( new NoStackTheme( new SmoothTheme() ) );
SplitDockStation station = new SplitDockStation();
frame.add( station );
frontend.addRoot( "split", station );
/* Prepare the Dockables we are going to put onto "station" */
Dockable red = new ColorDockable( "Red", Color.RED, 2.5f );
Dockable green = new ColorDockable( "Green", Color.GREEN, 2.5f );
Dockable blue = new ColorDockable( "Blue", Color.BLUE, 2.5f );
Dockable yellow = new ColorDockable( "Yellow", Color.YELLOW, 2.5f );
Dockable cyan = new ColorDockable( "Cyan", Color.CYAN, 2.5f );
Dockable magenta = new ColorDockable( "Magenta", Color.MAGENTA, 2.5f );
/* We will show the persistent data on this JTextArea */
TextDockable layout = new TextDockable( "File" );
/* Never forget to register all Dockables at the DockFrontend */
frontend.addDockable( "red", red );
frontend.addDockable( "green", green );
frontend.addDockable( "blue", blue );
frontend.addDockable( "yellow", yellow );
frontend.addDockable( "cyan", cyan );
frontend.addDockable( "magenta", magenta );
frontend.addDockable( "file", layout );
/* Adding the Dockables to "station" */
SplitDockGrid grid = new SplitDockGrid();
grid.addDockable( 0, 0, 40, 100, red, green, blue );
grid.setSelected( 0, 0, 40, 100, green );
grid.addDockable( 40, 0, 60, 30, yellow );
grid.addDockable( 40, 30, 20, 70, cyan );
grid.addDockable( 60, 30, 40, 70, magenta );
grid.addDockable( -40, 0, 40, 100, layout );
station.dropTree( grid.toTree() );
/* We build a menu that allows us to call the different methods easily */
JMenu menu = new JMenu( "Layout" );
/* The ReadAction calls DockFrontend.readXML */
ReadAction read = new ReadAction( frontend, layout );
menu.add( read );
/* The WriteAction calls DockFrontend.writeXML */
menu.add( new WriteAction( frontend, layout, read ) );
menu.addSeparator();
/* The LoadAction calls DockFrontend.load */
menu.add( new LoadAction( frontend ) );
/* The SaveAction calls DockFrontend.save() */
menu.add( new SaveAction( frontend ) );
/* The SaveAsAction calls DockFrontend.save(...) */
menu.add( new SaveAsAction( frontend ) );
/* Finally the DeleteAction calls DockFrontend.delete */
menu.add( new DeleteAction( frontend ) );
JMenuBar menuBar = new JMenuBar();
menuBar.add( menu );
frame.setJMenuBar( menuBar );
frame.setVisible( true );
}
/* This abstract action stores a DockFrontend to be used by its subclasses */
public static abstract class FrontendAction extends AbstractAction{
protected DockFrontend frontend;
public FrontendAction( String text, DockFrontend frontend ){
putValue( NAME, text );
this.frontend = frontend;
}
}
/* This action opens a dialog on which the user can choose one of the available
* layouts. The subclass decides what todo with the layout. */
public static abstract class FrontendLayoutListAction extends FrontendAction{
public FrontendLayoutListAction( String text, DockFrontend frontend ){
super( text, frontend );
/* A listener to "frontend" will tell us when there are layouts
* available and when not */
frontend.addFrontendListener( new DockFrontendAdapter() {
@Override
public void saved( DockFrontend frontend, String name ){
setEnabled( !frontend.getSettings().isEmpty() );
}
@Override
public void deleted( DockFrontend frontend, String name ){
setEnabled( !frontend.getSettings().isEmpty() );
}
@Override
public void read( DockFrontend frontend, String name ){
setEnabled( !frontend.getSettings().isEmpty() );
}
});
setEnabled( !frontend.getSettings().isEmpty() );
}
public void actionPerformed( ActionEvent e ){
/* "getSettings" gets us an unmodifiable Set containing the names
* of all the available layouts */
Set<String> settings = frontend.getSettings();
String[] list = settings.toArray( new String[ settings.size() ] );
Arrays.sort( list );
String layout = (String)JOptionPane.showInputDialog( frontend.getController().findRootWindow(),
"Choose one", "Input", JOptionPane.INFORMATION_MESSAGE, null, list, frontend.getCurrentSetting() );
if( layout != null ){
action( layout );
}
}
protected abstract void action( String settingName );
}
public static class SaveAction extends FrontendAction{
public SaveAction( DockFrontend frontend ){
super( "Save", frontend );
}
public void actionPerformed( ActionEvent e ){
/* "save()" stores the current layout using the name of the last loaded layout. If there
* is no last loaded layout then we have choose a name */
if( frontend.getCurrentSetting() == null ){
String name = JOptionPane.showInputDialog( frontend.getController().findRootWindow(), "Please input name of layout" );
if( name != null ){
frontend.save( name );
}
}
else{
frontend.save();
}
}
}
public static class SaveAsAction extends FrontendAction{
public SaveAsAction( DockFrontend frontend ){
super( "Save As...", frontend );
}
public void actionPerformed( ActionEvent e ){
String name = JOptionPane.showInputDialog( frontend.getController().findRootWindow(), "Please input name of layout" );
if( name != null ){
frontend.save( name );
}
}
}
public static class LoadAction extends FrontendLayoutListAction{
public LoadAction( DockFrontend frontend ){
super( "Load", frontend );
}
@Override
protected void action( String settingName ){
/* Cannot say much about that, just calling "load" with one of the
* available layouts */
frontend.load( settingName );
}
}
public static class DeleteAction extends FrontendLayoutListAction{
public DeleteAction( DockFrontend frontend ){
super( "Delete", frontend );
}
@Override
protected void action( String settingName ){
frontend.delete( settingName );
}
}
public static class WriteAction extends FrontendAction{
private TextDockable target;
private ReadAction opposite;
public WriteAction( DockFrontend frontend, TextDockable target, ReadAction opposite ){
super( "Write", frontend );
this.target = target;
this.opposite = opposite;
opposite.setEnabled( false );
}
public void actionPerformed( ActionEvent e ){
/* We convert all available layouts and the current layout to xml and
* show the text on our TextDockable */
XElement xroot = new XElement( "layout" );
frontend.writeXML( xroot );
target.setText( xroot.toString() );
opposite.setEnabled( true );
}
}
public static class ReadAction extends FrontendAction{
private TextDockable source;
public ReadAction( DockFrontend frontend, TextDockable source ){
super( "Read", frontend );
this.source = source;
}
public void actionPerformed( ActionEvent e ){
try{
/* "read" does not delete already existing layouts, so we clean up
* before applying a new set of layouts. */
Set<String> layouts = frontend.getSettings();
String[] keys = layouts.toArray( new String[ layouts.size() ] );
for( String key : keys ){
frontend.delete( key );
}
/* And now we can safely apply the old layouts */
XElement xroot = XIO.read( source.getText() );
frontend.readXML( xroot );
}
catch( IOException ex ){
ex.printStackTrace();
}
}
}
}