package jas.util; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dialog; import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; import java.util.StringTokenizer; import java.util.Vector; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.KeyStroke; /** * This class is meant to provide access from all packages to * certain general-purpose items of the application, such as * the UserProperties objects that the application * uses, and the JFrame that the application is in. It allows * classes from all packages to show help topics. However, * getting the actual topics themselves is the responsibility * of a class which subclasses Application. * @see UserProperties * @see javax.swing.JFrame * @author Jonas Gifford * @author Peter Armstrong */ abstract public class Application extends javax.swing.JPanel { /** * Creates an instance of the Application. This constructor may * only be called once in an application. */ public Application() { super(new BorderLayout()); if (app != null) throw new RuntimeException("Cannot make two applications."); app = this; //Add the options that the Application needs. gopt.addOption("debug", 'd', false, "Takes a : separated list of debug modes to set"); gopt.addOption("help", 'h', true, "Print this message"); //Register the help and F1 keys to show the help contents. ActionListener helpListener = new ActionListener() { public void actionPerformed(ActionEvent e) { showHelpContents(); } }; registerKeyboardAction( helpListener, KeyStroke.getKeyStroke(KeyEvent.VK_HELP, 0), JComponent.WHEN_IN_FOCUSED_WINDOW ); registerKeyboardAction( helpListener, KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0), JComponent.WHEN_IN_FOCUSED_WINDOW ); } /** * Called to parse the command line arguments (after setting appropriate * options) * @param argv The command line arguments * @return The number of parameters found * @see #getGetOptions */ protected int parseArgs(String[] argv) { //Now parse the command line arguments and act accordingly try { gopt.parseArgs(argv); } catch (GetOptions.BadArguments x) { doHelp(); System.out.println("The command line options you specified had the following problem:\n" + x.getMessage()); System.exit(0); } if (gopt.hasOption("help")) { doHelp(); System.exit(0); } setDebugFlags(); return gopt.numParams(); } /** * Called to show user the syntax of the command, as a result of a syntax error * in the command line arguments, or in response to the --help option * Override to provide specialized instructions for your application */ protected void doHelp() { gopt.dumpOptions(); } private void initializeHelpSystem() throws Exception { // Implemented this way so the appplication still runs even if the jar file // with the help system is not in the Class Path if (debugHelp) System.err.println("Initializing help system..."); try { hi = (HelpInterface)(Class.forName("jas.util.HelpInterfaceImpl")).newInstance(); if (debugHelp) System.err.println("Help system initialized successfully"); } catch (Exception x) { if (debugHelp) System.err.println("Failed: "+x.getMessage()); throw x; } } /** * Add a Help location to the Vector of locations to look in for the helpset. * At the time of writing, this was a one-element Vector, but we're being flexible :-) */ public void addHelpLocation(Class base,String s) { addHelpLocation(base.getResource(s)); } public void addHelpLocation(URL url) { if (debugHelp) System.err.println("addHelpLocation: "+url); if (url != null) theHelpLocations.addElement(url); } public void addHelpLocation(String s) { try { if (debugHelp) System.err.println("addHelpLocation: "+s); theHelpLocations.addElement(new URL(s)); } catch (MalformedURLException x) { System.err.println("Bad URL for addHelpLocation - ignored: "+s); x.printStackTrace(); } } /** * Get an Enumeration of all the locations to look in for the helpset. */ Enumeration getHelpLocations() { return theHelpLocations.elements(); } private void setDebugFlags() { //Now we can ask gopt about the command-line parameters in order to set our flags. if (gopt.hasOption("debug")) { StringTokenizer st = new StringTokenizer(gopt.getOption("debug"), ":"); while (st.hasMoreTokens()) { setDebugFlag(st.nextToken()); } } } /** * Called once for each debug flag set in the command options. * By default sets a system property of the form debugFlag where flag * is the flag specified (with its initial letter uppercased). * Override for application specific behaviour. */ protected void setDebugFlag(String flag) { String name = "debug" +flag.substring(0,1).toUpperCase()+flag.substring(1); System.getProperties().put(name,"true"); System.out.println("Set debug flag "+name); if (flag.equals("help")) debugHelp = true; } /** * Returns the application. */ static final public Application getApplication() { return app; } /** * Returns the UserProperties object. */ final public UserProperties getUserProperties() { return m_prop; } /** * Returns the parent JFrame. * @see javax.swing.JFrame */ final public JFrame getFrame() { if (m_parent == null) { Component parent = this; while (parent != null && !(parent instanceof JFrame)) parent = parent.getParent(); m_parent = (JFrame) parent; } return m_parent; } /** * Shows the table of contents for the help system. */ public final void showHelpContents() { showHelpTopic("top"); } /** * Shows the index for the help system. */ public final void showHelpIndex() { showHelpTopic("top", "Index"); } /** * Opens a search window for the help system. */ public final void showHelpSearch() { showHelpTopic("top", "Search"); } /** * Parents an error box to the application's frame and displays a Throwable * object's stack trace. * @see ErrorBox * @param s an error message * @param t the Exception or Error that caused the error */ public final void error(final String s, final Throwable t) { if (getFrame() != null) new ErrorBox(getFrame(), s, t).doModal(); else System.err.println("Error: "+s+" "+t); } /** * Parents an error box to the application's frame. * @see ErrorBox * @param s an error message */ public final void error(final String s) { if (getFrame() != null) new ErrorBox(getFrame(), s).doModal(); else System.err.println("Error: "+s); } /** * Parents an error box to the application's frame, displays a Throwable * object's stace trace, and contains a button that opens a given help page. * @see ErrorBox * @param s an error message * @param t the Exception or Error that caused the error * @param helpTopic the topic you want to link to */ public final void error(final String s, final Throwable t, final String helpTopic) { if (getFrame() != null) new ErrorBox(getFrame(), s, t, helpTopic).doModal(); else System.err.println("Error: "+s+" "+t); } /** * Parents an error box to the application's frame, and contains a button * that opens a given help page. * @see ErrorBox * @param s an error message * @param helpTopic the topic you want to link to */ public final void error(final String s, final String helpTopic) { if (getFrame() != null) new ErrorBox(getFrame(), s, helpTopic).doModal(); else System.err.println("Error: "+s); } public final void showHelpTopic(String helpTopicTarget) { showHelpTopic(helpTopicTarget,getFrame()); } /** * Shows the specified JavaHelp topic with the TOC visible * @param helpTopicTarget the JavaHelp XML target name which maps to the .html page in the map file */ public final void showHelpTopic(String helpTopicTarget, Window owner) { try { if (hi == null) initializeHelpSystem(); hi.showHelpTopic(helpTopicTarget,owner); } catch (Throwable eek) { whine(eek); } } /** * Shows the specified JavaHelp topic according to the display parameters provided. * @param helpTopicTarget the JavaHelp XML target name which maps to the .html page in the map file * @param navigatorView the string specifying which of the three views to have visible */ private final void showHelpTopic(String helpTopicTarget, String navigatorView) { try { if (hi == null) initializeHelpSystem(); hi.showHelpTopic(helpTopicTarget, navigatorView, getFrame()); } catch (Throwable eek) { whine(eek); } } private final void whine(Throwable eek) { app.error("Could not initialize help system!",eek); } /** * Get the GetOptions object that will be used to parse the command line arguments */ public GetOptions getGetOptions() { return gopt; } public CommandTargetManager getCommandManager() { return m_commandTargetManager; } /** * Workaround for modal dialog/help interface interaction */ void modalDialogOpening(Dialog dlg) { if (hi != null) hi.modalDialogOpening(dlg); } void modalDialogClosing(Dialog dlg) { if (hi != null) hi.modalDialogClosing(dlg); } private CommandTargetManager m_commandTargetManager = new CommandTargetManager(); private Vector theHelpLocations = new Vector(); private static Application app = null; private boolean debugHelp = false; private JFrame m_parent; private final UserProperties m_prop = new UserProperties(); private GetOptions gopt = new GetOptions(); private HelpInterface hi = null; }