001package hirondelle.stocks.help;
002
003import java.awt.event.*;
004import javax.swing.*;
005import java.util.logging.*;
006import javax.help.*;
007import java.net.URL;
008import hirondelle.stocks.util.Args;
009import hirondelle.stocks.util.Util;
010
011/**
012* Display the help system for the application.
013*
014* <P>Display one of table of contents, index, or search tab, according 
015* to argument passed to the constructor. This implementation uses 
016* Sun's <a href=http://java.sun.com/products/javahelp/>JavaHelp</a> tool.
017*
018* <P>This action activates the Help key (often <tt>F1</tt>) for this application. 
019* When the help key is pressed, the help system's table of contents is displayed.
020*
021* <P>This action is unusual in that it corresponds to more than one menu item 
022* (Contents, Index, and Search).
023*
024* <P>Note: the displayed JavaHelp screen is not centered; it's left as is, 
025* since the JavaHelp GUI is often cut off at the bottom anyway, and centering would 
026* make this problem worse.
027*/
028public final class HelpAction extends AbstractAction {
029
030  /**
031  * Constructor.
032  *  
033  * @param aFrame parent window to which the help window is attached
034  * @param aText name of the menu item for this help action
035  * @param aMnemonicKeyEvent mnemonic for <tt>aText</tt>
036  * @param aIcon possibly-null graphic to be displayed alongside the text, or 
037  * in a toolbar
038  * @param aView determines which help window is to be displayed: Contents, Index, 
039  * or Search
040  */
041  public HelpAction(
042    JFrame aFrame, String aText, int aMnemonicKeyEvent, Icon aIcon, View aView
043  ) {
044    super(aText, aIcon);
045    Args.checkForNull(aFrame);
046    Args.checkForNull(aText);
047    Args.checkForNull(aView);
048    fFrame = aFrame;
049    fView = aView;
050    putValue(SHORT_DESCRIPTION, "StocksMonitor Help");
051    putValue(LONG_DESCRIPTION, "Displays JavaHelp for StocksMonitor.");
052    putValue(MNEMONIC_KEY, new Integer(aMnemonicKeyEvent) );    
053    initHelpSystem(); 
054  }
055
056  @Override public void actionPerformed(ActionEvent event) {
057    fLogger.info("Showing help system.");
058    fHelpBroker.setCurrentView( fView.toString() );
059    fDisplayHelp.actionPerformed( event );
060  }
061  
062  /** Enumeration for the style of presentation of the the Help system. */
063  public enum View {
064    SEARCH("Search"), 
065    CONTENTS("TOC"), 
066    INDEX("Index");
067    @Override public String toString(){
068      return fName;
069    }
070    private View(String aName){
071      fName = aName;
072    }
073    private String fName;
074  } 
075
076  // PRIVATE 
077  private JFrame fFrame;
078  private View fView;
079  /** Path used by a classloader to find the JavaHelp files. */
080  private static final String PATH_TO_JAVA_HELP =
081    "hirondelle/stocks/help/JavaHelp/HelpSet.hs"
082  ;
083  private ClassLoader DEFAULT_CLASS_LOADER = null;
084  private static final Logger fLogger = Util.getLogger(HelpAction.class); 
085  
086  private HelpBroker fHelpBroker;
087  private CSH.DisplayHelpFromSource fDisplayHelp;
088  
089  /** Initialize the JavaHelp system. */
090  private void initHelpSystem(){
091    //optimization to avoid repeated init
092    if ( fHelpBroker != null && fDisplayHelp != null) return;
093    
094    //(uses the classloader mechanism)
095    ClassLoader loader = this.getClass().getClassLoader();
096    URL helpSetURL = HelpSet.findHelpSet(loader, PATH_TO_JAVA_HELP);
097    assert helpSetURL != null : "Cannot find help system.";
098    try {
099      HelpSet helpSet = new HelpSet(DEFAULT_CLASS_LOADER, helpSetURL);
100      fHelpBroker = helpSet.createHelpBroker();
101      fHelpBroker.enableHelpKey( fFrame.getRootPane(), "overview", helpSet );
102      fDisplayHelp = new CSH.DisplayHelpFromSource(fHelpBroker);
103    }
104    catch (HelpSetException ex) {
105      fLogger.severe("Cannot create help system with: " + helpSetURL);
106    }
107    assert fHelpBroker != null : "HelpBroker is null.";
108  }
109}