package bibliothek.notes.view;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import bibliothek.demonstration.util.LookAndFeelMenu;
import bibliothek.gui.DockStation;
import bibliothek.gui.DockTheme;
import bibliothek.notes.Core;
import bibliothek.notes.model.Note;
import bibliothek.notes.util.ResourceSet;
import bibliothek.notes.view.menu.HelpMenu;
import bibliothek.notes.view.menu.PanelList;
import bibliothek.notes.view.menu.PreferenceItem;
import bibliothek.notes.view.menu.ThemeMenu;
import bibliothek.util.xml.XElement;
/**
* The most important frame of this application. This frame shows the
* menu and contains the {@link DockStation}s in which the {@link Note}s
* are displayed.
* @author Benjamin Sigg
*
*/
public class MainFrame extends JFrame{
/** the center of the application */
private Core core;
/** the menu for the {@link DockTheme}s */
private ThemeMenu themes;
/** the dialog that shows the authors and libraries of this application */
private About about;
/**
* Creates a new frame. The content of the frame is not created by
* this constructor, clients must call {@link #setup(Core)}.
*/
public MainFrame(){
setTitle( "Notes - Demonstration of DockingFrames" );
setDefaultCloseOperation( DO_NOTHING_ON_CLOSE );
setIconImage( ResourceSet.toImage( ResourceSet.APPLICATION_ICONS.get( "application" )));
}
/**
* Creates the content of this frame. These are the {@link DockStation}s
* and the menus. It's unspecified what happens when this method is called
* twice.
* @param core the center of the application, not <code>null</code>
*/
public void setup( Core core ){
this.core = core;
setupStations();
setupListeners();
setupMenu();
}
/**
* Creates and adds all {@link DockStation}s that are displayed on
* this {@link MainFrame}.
*/
private void setupStations(){
Container content = getContentPane();
content.setLayout( new BorderLayout() );
content.add( core.getViews().getSplit(), BorderLayout.CENTER );
content.add( core.getViews().getNorth().getComponent(), BorderLayout.NORTH );
content.add( core.getViews().getSouth().getComponent(), BorderLayout.SOUTH );
content.add( core.getViews().getEast().getComponent(), BorderLayout.EAST );
content.add( core.getViews().getWest().getComponent(), BorderLayout.WEST );
}
/**
* Creates and adds all observers that are needed by this {@link MainFrame}.
*/
private void setupListeners(){
addWindowListener( new WindowAdapter(){
@Override
public void windowClosing( WindowEvent e ){
core.shutdown();
}
});
}
/**
* Creates and adds all menus and the menubar.
*/
private void setupMenu(){
JMenuBar menubar = new JMenuBar();
menubar.add( new PanelList( core.getViews(), core.getModel() ));
JMenu theme = new JMenu( "Window" );
themes = new ThemeMenu( core.getViews().getFrontend() );
theme.add( new LookAndFeelMenu( this, core.getLookAndFeels() ) );
theme.add( themes );
theme.add( new PreferenceItem( this, core.getPreferences() ));
menubar.add( theme );
menubar.add( new HelpMenu( this ) );
setJMenuBar( menubar );
}
/**
* Writes location, extended-state and theme of this frame.
* @param out the stream to write into
* @throws IOException if the method can't write into <code>out</code>
*/
public void write( DataOutputStream out ) throws IOException{
out.writeInt( getExtendedState() );
setExtendedState( NORMAL );
out.writeInt( getX() );
out.writeInt( getY() );
out.writeInt( getWidth() );
out.writeInt( getHeight() );
themes.write( out );
}
/**
* Reads location, extended-state and theme of this frame.
* @param in the stream to read from
* @throws IOException if the stream can't be read
*/
public void read( DataInputStream in ) throws IOException{
int state = in.readInt();
setBounds( in.readInt(), in.readInt(), in.readInt(), in.readInt() );
setExtendedState( state );
themes.read( in );
}
/**
* Writes location, extended-state and theme of this frame.
* @param element the xml-element to write into
*/
public void writeXML( XElement element ){
element.addElement( "extended" ).setInt( getExtendedState() );
setExtendedState( NORMAL );
XElement xbounds = element.addElement( "bounds" );
xbounds.addInt( "x", getX() );
xbounds.addInt( "y", getY() );
xbounds.addInt( "width", getWidth() );
xbounds.addInt( "height", getHeight() );
themes.writeXML( element.addElement( "theme" ) );
}
/**
* Reads location, extended-state and theme of this frame.
* @param element the xml-element to read from
*/
public void readXML( XElement element ){
int state = element.getElement( "extended" ).getInt();
XElement xbounds = element.getElement( "bounds" );
setBounds( xbounds.getInt( "x" ), xbounds.getInt( "y" ), xbounds.getInt( "width" ), xbounds.getInt( "height" ) );
setExtendedState( state );
themes.readXML( element.getElement( "theme" ) );
}
/**
* Gets the about-dialog of this application.
* @param lazy <code>true</code> if the dialog should be newly created if
* it is <code>null</code>, or <code>false</code> if the current value
* of the property should be returned.
* @return the dialog, maybe <code>null</code> but only if <code>lazy</code>
* was <code>false</code>
*/
public About getAbout( boolean lazy ){
if( about == null && lazy ){
about = new About( this );
about.pack();
about.setLocationRelativeTo( this );
}
return about;
}
}