package tutorial.common.basics; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.GridLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JToggleButton; import tutorial.support.JTutorialFrame; import tutorial.support.Tutorial; import bibliothek.gui.dock.common.CContentArea; import bibliothek.gui.dock.common.CControl; import bibliothek.gui.dock.common.CLocation; import bibliothek.gui.dock.common.DefaultMultipleCDockable; import bibliothek.gui.dock.common.EmptyMultipleCDockableFactory; import bibliothek.gui.dock.common.MultipleCDockable; import bibliothek.gui.dock.util.FocusedWindowProvider; @Tutorial( id="MultiFrame", title="Multiple Frames" ) public class MultiFrameExample { /* This example demonstrates how the framework deals with multiple JFrames, and how an application must * be modified to support multiple JFrames. * * The example allows up to 4 JFrames to show up. All JFrames have the exact same properties, and there is no * way to tell which one is the "main" JFrame. Also users can close and open new JFrames at any time. * * Clients with a similar layout will need to use the FocusedWindowProvider and should not call * CControl.getContentArea(). Otherwise no additional configuration is needed. */ public static void main( String[] args ){ /* Since there is not one but many main-Frames, it is hard to specify which one is the root-window. The * FocusedWindowProvider always assumes that the window that is or was focused is the root-window. */ FocusedWindowProvider windows = new FocusedWindowProvider(); /* One of the constructors of CControl allows to set the root-window provider directly */ CControl control = new CControl( windows ); /* We need some kind of application object that helps with managing the JFrames */ Application application = new Application( control, windows ); for( int i = 0; i < 4; i++ ){ application.switchFrame( i ); } } /* We are going to show some MultipleCDockables. While this factory could create these dockables, it is actually * never used. It exists only because the API forces us to provide a factory. */ private static class Factory extends EmptyMultipleCDockableFactory<MultipleCDockable>{ @Override public MultipleCDockable createDockable(){ return newDockable( this ); } } /* This method actually creates new Dockables that we are going to show. Each Dockable shows a panel * with a randomly chosen color. */ private static MultipleCDockable newDockable( Factory factory ){ int random = (int)(Math.random() * 255 * 255 * 255); DefaultMultipleCDockable dockable = new DefaultMultipleCDockable( factory ); dockable.setTitleText( String.valueOf( random ) ); dockable.setRemoveOnClose( true ); dockable.setCloseable( true ); JPanel panel = new JPanel(); panel.setOpaque( true ); panel.setBackground( new Color( random ) ); dockable.add( panel ); return dockable; } /* This is a panel showing four JToggleButtons. A button that is selected represents a JFrame * that is visible, a button that is not selected represents a JFrame that is invisible. * * Each JFrame will show one of this panels. */ private static class FrameSwitchPanel extends JPanel{ private JToggleButton[] buttons = new JToggleButton[4]; private Application application; public FrameSwitchPanel( Application application ){ setLayout( new GridLayout( 2, 2 ) ); this.application = application; for( int i = 0; i < buttons.length; i++ ){ buttons[i] = initButton( i ); add( buttons[i] ); } } private JToggleButton initButton( final int index ){ JToggleButton button = new JToggleButton( String.valueOf( index )); button.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e ){ /* If the user clicks on the button we make the JFrame visible or invisible */ application.switchFrame( index ); } }); return button; } public void setOpened( int index, boolean open ){ buttons[index].setSelected( open ); } } /* A JFrame containing one CContentArea */ private static class ExampleFrame extends JTutorialFrame{ private FrameSwitchPanel switcher; private CContentArea area; public ExampleFrame( final int location, final Application application ){ super( MultiFrameExample.class ); /* Registering some control buttons, and also making sure all references to this * JFrame are removed once this frame has been closed. */ switcher = new FrameSwitchPanel( application ); application.addSwitcher( switcher ); addWindowListener( new WindowAdapter(){ @Override public void windowClosed( WindowEvent e ){ application.removeSwitcher( switcher ); application.getControl().removeStationContainer( area ); } }); /* We create a new CContentArea that is shown on this JFrame. We choose a unique identifier that does * not collide with existing identifiers. */ CControl control = application.getControl(); area = control.createContentArea( "area " + location ); /* Inform the framework about the existence of this Window */ application.getWindows().add( this ); /* A button for creating new Dockables */ JButton add = new JButton("New dockable"); add.addActionListener( new ActionListener(){ public void actionPerformed( ActionEvent e ){ application.createDockable( location ); } }); /* Now we add all Components to this JFrame. */ JPanel north = new JPanel( new GridBagLayout() ); north.add( switcher, new GridBagConstraints( 0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 0, 0, 0, 0 ), 0, 0 )); north.add( add, new GridBagConstraints( 1, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets( 0, 0, 0, 0 ), 0, 0 )); add( north, BorderLayout.NORTH ); add( area, BorderLayout.CENTER ); /* Finally setting a location such that all JFrames will appear next to each other */ switch( location ){ case 0: setBounds( 20, 20, 400, 400 ); break; case 1: setBounds( 420, 20, 400, 400 ); break; case 2: setBounds( 20, 420, 400, 400 ); break; case 3: setBounds( 420, 420, 400, 400 ); break; } } public CContentArea getArea(){ return area; } } /* The Application object is responsible for connecting the JFrames */ private static class Application { private List<FrameSwitchPanel> switchers = new ArrayList<FrameSwitchPanel>(); private ExampleFrame[] frames = new ExampleFrame[4]; private CControl control; private Factory factory; private FocusedWindowProvider windows; /* Informs the FrameSwitchPanel which JFrames are visible and which are not */ private WindowListener framesListener = new WindowAdapter(){ public void windowOpened( WindowEvent e ){ int index = indexOf( (ExampleFrame)e.getWindow() ); for( FrameSwitchPanel switcher : switchers ){ switcher.setOpened( index, true ); } } public void windowClosed( WindowEvent e ){ int index = indexOf( (ExampleFrame)e.getWindow() ); for( FrameSwitchPanel switcher : switchers ){ switcher.setOpened( index, false ); } windows.remove( e.getWindow() ); frames[index].removeWindowListener( this ); frames[index].dispose(); frames[index] = null; } }; public Application( CControl control, FocusedWindowProvider windows ){ this.control = control; this.windows = windows; factory = new Factory(); control.addMultipleDockableFactory( "color", factory ); } private int indexOf( ExampleFrame frame ){ for( int i = 0; i < frames.length; i++ ){ if( frames[i] == frame ){ return i; } } return -1; } /* Either shows or hides the JFrame 'index' */ public void switchFrame(int index){ if(frames[index] == null){ frames[index] = new ExampleFrame( index, this ); frames[index].addWindowListener( framesListener ); frames[index].setVisible( true ); } else{ frames[index].dispose(); } } /* Creates a new Dockable and adds it to the JFrame 'index' */ public void createDockable( int index ){ MultipleCDockable dockable = newDockable( factory ); control.addDockable( dockable ); dockable.setLocation( CLocation.base( frames[index].getArea() ).normal() ); dockable.setVisible( true ); } public void addSwitcher(FrameSwitchPanel panel){ switchers.add( panel ); for( int i = 0; i < frames.length; i++ ){ panel.setOpened( i, frames[i] != null ); } } public void removeSwitcher( FrameSwitchPanel panel ){ switchers.remove( panel ); } public CControl getControl(){ return control; } public FocusedWindowProvider getWindows(){ return windows; } } }