package tutorial.common.guide; import java.awt.Color; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import javax.swing.JMenuBar; import javax.swing.JScrollPane; import javax.swing.JTextArea; import tutorial.support.JTutorialFrame; import tutorial.support.Tutorial; import bibliothek.gui.dock.common.CControl; import bibliothek.gui.dock.common.CGrid; import bibliothek.gui.dock.common.DefaultMultipleCDockable; import bibliothek.gui.dock.common.MultipleCDockableFactory; import bibliothek.gui.dock.common.MultipleCDockableLayout; import bibliothek.gui.dock.common.menu.CLayoutChoiceMenuPiece; import bibliothek.gui.dock.facile.menu.RootMenuPiece; import bibliothek.util.xml.XElement; @Tutorial( id="MultipleDockables", title="\"Editors\": MultipleCDockable") public class MultipleDockables { /* There are two kind of CDockables: SingleCDockables and MultipleCDockables. This * example shows how MultipleCDockables are used to build an unknown number of editors. * In this case an editor is some kind of panel where the user can edit something, for * example a text file. * * In order to use a MultipleCDockable clients normally write three classes. In this * example the three classes are as follows: * - EditorDockable: the MultipleCDockable that is actually displayed and which is "the editor" * - EditorLayout: a MultipleCDockableLayout which contains information about the content of * an EditorDocakble. The EditorLayout is lightweight, meaning it does not consume a * lot of memory (directly or indirectly through references). * - EditorFactory: a factory that creates new EditorDockables given some EditorLayouts. */ public static void main( String[] args ){ /* We start by setting up a frame and a CControl */ JTutorialFrame frame = new JTutorialFrame( MultipleDockables.class ); CControl control = new CControl( frame ); frame.destroyOnClose( control ); frame.add( control.getContentArea() ); /* We need to install our EditorFactory early on, otherwise the framework will not * allow us to register the EditorDockables. */ EditorFactory factory = new EditorFactory(); control.addMultipleDockableFactory( "file-editor", factory ); /* We now create some dockables and drop them onto the content-area */ CGrid grid = new CGrid( control ); grid.add( 0, 0, 1, 1, new EditorDockable( factory, new EditorLayout( "/home/tutorial/one.txt", "one = 1", new Color( 255, 200, 200 ) ) ) ); grid.add( 0, 1, 1, 1, new EditorDockable( factory, new EditorLayout( "/home/tutorial/two.txt", "two = 2", new Color( 255, 255, 200 ) ) ) ); grid.add( 1, 0, 1, 1, new EditorDockable( factory, new EditorLayout( "/home/tutorial/three.txt", "three = 3", new Color( 200, 255, 200 ) ) ) ); grid.add( 1, 1, 1, 1, new EditorDockable( factory, new EditorLayout( "/home/tutorial/four.txt", "four = 4", new Color( 200, 200, 255 ) ) ) ); control.getContentArea().deploy( grid ); /* The CLayoutChoiceMenuPiece creates a dynamic menu which allows us to * save and load the layout. In doing so we will use the EditorFactory. */ JMenuBar menubar = new JMenuBar(); RootMenuPiece layout = new RootMenuPiece( "Layout", false ); layout.add( new CLayoutChoiceMenuPiece( control, true ) ); menubar.add( layout.getMenu() ); frame.setJMenuBar( menubar ); /* and finally we can start the application */ frame.setVisible( true ); } /* This dockable shows the contents of a (fake) text file. */ private static class EditorDockable extends DefaultMultipleCDockable{ private JTextArea text; public EditorDockable( EditorFactory factory, EditorLayout layout ){ /* it is mandatory to set the factory, the EditorDockable cannot be created * without it. */ super( factory ); /* and then we just set up the editor */ setTitleText( layout.getFileName() ); text = new JTextArea(); text.setText( layout.getFileContent() ); text.setBackground( layout.getBackground() ); add( new JScrollPane( text ) ); } /* This convenient method allows us to grab the entire content of this dockable * in one step. */ public EditorLayout getLayout(){ return new EditorLayout( getTitleText(), text.getText(), text.getBackground() ); } } /* This factory builds a link between EditorDockable and EditorLayout */ private static class EditorFactory implements MultipleCDockableFactory<EditorDockable, EditorLayout>{ /* An empty layout is required to read a layout from an XML file or from a byte stream */ public EditorLayout create(){ return new EditorLayout(); } /* An optional method allowing to reuse 'dockable' when loading a new layout */ public boolean match( EditorDockable dockable, EditorLayout layout ){ return dockable.getLayout().equals( layout ); } /* Called when applying a stored layout */ public EditorDockable read( EditorLayout layout ){ return new EditorDockable( this, layout ); } /* Called when storing the current layout */ public EditorLayout write( EditorDockable dockable ){ return dockable.getLayout(); } } /* This class describes the content of an EditorDockable. */ private static class EditorLayout implements MultipleCDockableLayout{ private String fileName; private String fileContent; private Color background; public EditorLayout(){ // nothing } public EditorLayout( String fileName, String fileContent, Color background ){ this.fileName = fileName; this.fileContent = fileContent; this.background = background; } public String getFileName(){ return fileName; } public String getFileContent(){ return fileContent; } public Color getBackground(){ return background; } @Override public boolean equals( Object obj ){ if( this == obj ){ return true; } if( obj == null ){ return false; } if( getClass() != obj.getClass() ){ return false; } EditorLayout other = (EditorLayout) obj; return equals( background, other.background ) && equals( fileName, other.fileName ) && equals( fileContent, other.fileContent ); } private boolean equals( Object a, Object b ){ if( a == null ){ return b == null; } else{ return a.equals( b ); } } public void readStream( DataInputStream in ) throws IOException{ fileName = in.readUTF(); fileContent = in.readUTF(); background = new Color( in.readInt() ); } public void readXML( XElement element ){ fileName = element.getElement( "name" ).getString(); fileContent = element.getElement( "content" ).getString(); background = new Color( element.getElement( "background" ).getInt() ); } public void writeStream( DataOutputStream out ) throws IOException{ out.writeUTF( fileName ); out.writeUTF( fileContent ); out.writeInt( background.getRGB() ); } public void writeXML( XElement element ){ element.addElement( "name" ).setString( fileName ); element.addElement( "content" ).setString( fileContent ); element.addElement( "background" ).setInt( background.getRGB() ); } } }