Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  
  /*
   * Copyright (C) 2006 Sun Microsystems, Inc. All rights reserved. Use is
   * subject to license terms.
   */ 
  
  package org.jdesktop.application;
  
 import java.awt.Frame;
 import java.util.List;
An application base class for simple GUIs with one primary JFrame.

This class takes care of component property injection, exit processing, and saving/restoring session state in a way that's appropriate for simple single-frame applications. The application's JFrame is created automatically, with a WindowListener that calls exit() when the window is closed. Session state is stored when the application shuts down, and restored when the GUI is shown.

To use SingleFrameApplication, one need only override startup, create the GUI's main panel, and apply show to that. Here's an example:

class MyApplication extends SingleFrameApplication {
    @Override protected void startup() {
        show(new JLabel("Hello World"));
    }
}
 
The call to show in this example creates a JFrame (named "mainFrame"), that contains the "Hello World" JLabel. Before the frame is made visible, the properties of all of the components in the hierarchy are initialized with ResourceMap.injectComponents and then restored from saved session state (if any) with SessionStorage.restore. When the application shuts down, session state is saved.

A more realistic tiny example would rely on a ResourceBundle for the JLabel's string and the main frame's title. The automatic injection step only initializes the properties of named components, so:

 class MyApplication extends SingleFrameApplication {
     @Override protected void startup() {
         JLabel label = new JLabel();
         label.setName("label");
         show(label);
     }
 }
 
The ResourceBundle should contain definitions for all of the standard Application resources, as well the main frame's title and the label's text. Note that the JFrame that's implicitly created by the show method is named "mainFrame".
 # resources/MyApplication.properties
 Application.id = MyApplication
 Application.title = My Hello World Application 
 Application.version = 1.0
 Application.vendor = Sun Microsystems, Inc.
 Application.vendorId = Sun
 Application.homepage = http://www.javadesktop.org
 Application.description =  An example of SingleFrameApplication
 Application.lookAndFeel = system
 
 mainFrame.title = ${Application.title} ${Application.version}
 label.text = Hello World
 
 
 public abstract class SingleFrameApplication extends Application {
     private static final Logger logger = Logger.getLogger(SingleFrameApplication.class.getName());
     private ResourceMap appResources = null;

    
Return the JFrame used to show this application.

The frame's name is set to "mainFrame", its title is initialized with the value of the Application.title resource and a WindowListener is added that calls exit when the user attempts to close the frame.

This method may be called at any time; the JFrame is created lazily and cached. For example:

 protected void startup() {
     getMainFrame().setJMenuBar(createMenuBar());
     show(createMainPanel());
 }
 

    public final JFrame getMainFrame() {
        return getMainView().getFrame();
    }

    
Sets the JFrame use to show this application.

This method should be called from the startup method by a subclass that wants to construct and initialize the main frame itself. Most applications can rely on the fact that {code getMainFrame} lazily constructs the main frame and initializes the mainFrame property.

If the main frame property was already initialized, either implicitly through a call to getMainFrame or by explicitly calling this method, an IllegalStateException is thrown. If mainFrame is null, an IllegalArgumentException is thrown.

This property is bound.

Parameters:
mainFrame the new value of the mainFrame property
See also:
getMainFrame()
    protected final void setMainFrame(JFrame mainFrame) {
        getMainView().setFrame(mainFrame);
    }
    private String sessionFilename(Window window) {
	if (window == null) {
	    return null
	}
	else {
	    String name = window.getName();
	    return (name == null) ? null : name + ".session.xml";
	}
    }

    
Initialize the hierarchy with the specified root by injecting resources.

By default the show methods inject resources before initializing the JFrame or JDialog's size, location, and restoring the window's session state. If the app is showing a window whose resources have already been injected, or that shouldn't be initialized via resource injection, this method can be overridden to defeat the default behavior.

    protected void configureWindow(Window root) {
    }
    private void initRootPaneContainer(RootPaneContainer c) {
	JComponent rootPane = c.getRootPane();
	// These initializations are only done once
	Object k = "SingleFrameApplication.initRootPaneContainer";
	if (rootPane.getClientProperty(k) != null) {
	    return;
	}
	// Inject resources
	Container root = rootPane.getParent();
	if (root instanceof Window) {
	    configureWindow((Window)root);
	}
	// If this is the mainFrame, then close == exit
        JFrame mainFrame = getMainFrame();
	if (c == mainFrame) {
	    mainFrame.addWindowListener(new MainFrameListener());
	}
	else if (root instanceof Window) { // close == save session state
	    Window window = (Window)root;
	}
        // If this is a JFrame monitor "normal" (not maximized) bounds
        if (root instanceof JFrame) {
            root.addComponentListener(new FrameBoundsListener());
        }
	// If the window's bounds don't appear to have been set, do it
	if (root instanceof Window) {
	    Window window = (Window)root;
            if (!root.isValid() || (root.getWidth() == 0) || (root.getHeight() == 0)) {
                window.pack();
            }
	    if (!window.isLocationByPlatform() && (root.getX() == 0) && (root.getY() == 0)) {
		Component owner = window.getOwner();
                if (owner == null) {
                    owner = (window != mainFrame) ? mainFrame : null;
                }
		window.setLocationRelativeTo(owner);  // center the window
	    }
	}
	// Restore session state
	if (root instanceof Window) {
	    String filename = sessionFilename((Window)root);
	    if (filename != null) {
		try {
		    getContext().getSessionStorage().restore(rootfilename);
		}
		catch (Exception e) {
                    String msg = String.format("couldn't restore sesssion [%s]"filename);
		    .log(.msg , e);
		}
	    }
	}
    }

    
Show the specified component in the main frame. Typical applications will call this method after constructing their main GUI panel in the startup method.

Before the main frame is made visible, the properties of all of the components in the hierarchy are initialized with ResourceMap.injectComponents(java.awt.Component) and then restored from saved session state (if any) with SessionStorage.restore(java.awt.Component,java.lang.String). When the application shuts down, session state is saved.

Note that the name of the lazily created main frame (see getMainFrame) is set by default. Session state is only saved for top level windows with a valid name and then only for component descendants that are named.

Throws an IllegalArgumentException if c is null

Parameters:
c the main frame's contentPane child
    protected void show(JComponent c) {
	if (c == null) {
	    throw new IllegalArgumentException("null JComponent");
	}
	f.setVisible(true);
    }

    
Initialize and show the JDialog.

This method is intended for showing "secondary" windows, like message dialogs, about boxes, and so on. Unlike the mainFrame, dismissing a secondary window will not exit the application.

Session state is only automatically saved if the specified JDialog has a name, and then only for component descendants that are named.

Throws an IllegalArgumentException if c is null

Parameters:
c the main frame's contentPane child
See also:
show(javax.swing.JComponent)
show(javax.swing.JFrame)
configureWindow(java.awt.Window)
    public void show(JDialog c) {
	if (c == null) {
	    throw new IllegalArgumentException("null JDialog");
	}
	c.setVisible(true);
    }

    
Initialize and show the secondary JFrame.

This method is intended for showing "secondary" windows, like message dialogs, about boxes, and so on. Unlike the mainFrame, dismissing a secondary window will not exit the application.

Session state is only automatically saved if the specified JFrame has a name, and then only for component descendants that are named.

Throws an IllegalArgumentException if c is null

    public void show(JFrame c) {
	if (c == null) {
	    throw new IllegalArgumentException("null JFrame");
	}
	c.setVisible(true);
    }
    private void saveSession(Window window) {
	String filename = sessionFilename(window);
	if (filename != null) {
	    try {
		getContext().getSessionStorage().save(windowfilename);
	    }
	    catch (IOException e) {
		.log(."couldn't save sesssion"e);
	    }
	}
    }
    private boolean isVisibleWindow(Window w) {
	return w.isVisible() && 
	    ((w instanceof JFrame) || (w instanceof JDialog) || (w instanceof JWindow));
    }

    
Return all of the visible JWindows, JDialogs, and JFrames per Window.getWindows() on Java SE 6, or Frame.getFrames() for earlier Java versions.
    private List<WindowgetVisibleSecondaryWindows() {
	List<Windowrv = new ArrayList<Window>();
	Method getWindowsM = null;
	try {
	    getWindowsM = Window.class.getMethod("getWindows");
	}
	catch(Exception ignore) {
	}
	if (getWindowsM != null) {
	    Window[] windows = null;
	    try {
		windows = (Window[])getWindowsM.invoke(null);
	    }
	    catch(Exception e) {
		throw new Error("HCTB - can't get top level windows list"e);
	    }
	    if (windows != null) {
		for(Window window : windows) {
		    if (isVisibleWindow(window)) {
			rv.add(window);
		    }
		}
	    }
	}
	else {
	    Frame[] frames = Frame.getFrames();
	    if (frames != null) {
		for(Frame frame : frames) {
		    if (isVisibleWindow(frame)) {
			rv.add(frame);
		    }
		}
	    }
	}
	return rv;
    }

    
Save session state for the component hierarchy rooted by the mainFrame. SingleFrameApplication subclasses that override shutdown need to remember call super.shutdown().
    @Override protected void shutdown() {
	for(Window window : getVisibleSecondaryWindows()) {
	    saveSession(window);
	}
    }
    private class MainFrameListener extends WindowAdapter {
	public void windowClosing(WindowEvent e) {
	    exit(e);
	}
    }
    /* Although it would have been simpler to listen for changes in
     * the secondary window's visibility per either a
     * PropertyChangeEvent on the "visible" property or a change in
     * visibility per ComponentListener, neither listener is notified
     * if the secondary window is disposed.
     * HierarchyEvent.SHOWING_CHANGED does report the change in all
     * cases, so we use that.
     */
    private class SecondaryWindowListener implements HierarchyListener {
	public void hierarchyChanged(HierarchyEvent e) {
	    if ((e.getChangeFlags() & .) != 0) {
		if (e.getSource() instanceof Window) {
		    Window secondaryWindow = (Window)e.getSource();
		    if (!secondaryWindow.isShowing()) {
			saveSession(secondaryWindow);
		    }
		}
	    }
	}
    }
    /* In order to properly restore a maximized JFrame, we need to 
     * record it's normal (not maximized) bounds.  They're recorded
     * under a rootPane client property here, so that they've can be 
     * session-saved by WindowProperty#getSessionState().
     */
    private static class FrameBoundsListener implements ComponentListener {
        private void maybeSaveFrameSize(ComponentEvent e) { 
            if (e.getComponent() instanceof JFrame) {
                JFrame f = (JFrame)e.getComponent();
                if ((f.getExtendedState() & .) == 0) {
                    String clientPropertyKey = "WindowState.normalBounds";
                    f.getRootPane().putClientProperty(clientPropertyKeyf.getBounds());
                }
            }
        }
        public void componentResized(ComponentEvent e) { maybeSaveFrameSize(e); }
        /* BUG: on Windows XP, with JDK6, this method is called once when the 
         * frame is a maximized, with x,y=-4 and getExtendedState() == 0.
         */
        public void componentMoved(ComponentEvent e) { /* maybeSaveFrameSize(e); */ }
        public void componentHidden(ComponentEvent e) { }
        public void componentShown(ComponentEvent e) { }
    }
    /* Prototype support for the View type */
    
    private FrameView mainView = null;
    public FrameView getMainView() {
        if ( == null) {
             = new FrameView(this);
        }
        return ;
    }
    public void show(View view) {
        if (( == null) && (view instanceof FrameView)) {
             = (FrameView)view;
        }
        initRootPaneContainer(c);
	((Window)c).setVisible(true);
    }
New to GrepCode? Check out our FAQ X