import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.tree.TreeSelectionModel;
import java.net.URL;
import java.io.IOException;
import javax.swing.JEditorPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;

/**
  The HelpBrowser module is something that I stole from 
  one of the swing examples on how to use JTrees. I thought
  it would be useful to have a list of documents that would
  introduce the user to Mozart and some of its features.
  I have several ideas to add to the module: 
  <UL>
    <Li>First is adding copy capiblity. 
    <LI>The next would be a "Back" button.
    <li>Separate the large code file into smaller chunks
        (HelpTree, HelpPane, etc).
  </ul>
  <br><br><a href="../source/HelpBrowser.java">View Source File</a>
*/

public class HelpBrowser extends JFrame {
  private JEditorPane htmlPane;
  private static boolean DEBUG = false;
  private URL helpURL;
  
  public HelpBrowser() {
    super("Mozart Help");
    
    //Create the nodes.
    DefaultMutableTreeNode top = new DefaultMutableTreeNode("The Mozart Project");
    createNodes(top);
    
    //Create a tree that allows one selection at a time.
    JTree tree = new JTree(top);
    tree.getSelectionModel().setSelectionMode
      (TreeSelectionModel.SINGLE_TREE_SELECTION);
    
    //Listen for when the selection changes.
    tree.addTreeSelectionListener(new TreeSelectionListener() {
      public void valueChanged(TreeSelectionEvent e) {
	DefaultMutableTreeNode node = (DefaultMutableTreeNode)
	  (e.getPath().getLastPathComponent());
	Object nodeInfo = node.getUserObject();

	if (node.isLeaf()) {
	  BookInfo book = (BookInfo)nodeInfo;
	  displayURL(book.bookURL);
	  if (DEBUG) {
	    System.out.print(book.bookURL + ":  \n    ");
	  }

	} else {
	  displayURL(helpURL); 
	}

	if (DEBUG) {
	  System.out.println(nodeInfo.toString());
	}
      }
    });

    //Create the scroll pane and add the tree to it. 
    JScrollPane treeView = new JScrollPane(tree);
    
    //Create the HTML viewing pane.
    htmlPane = new JEditorPane();
    htmlPane.setEditable(false);
    initHelp();
    JScrollPane htmlView = new JScrollPane(htmlPane);
    
    htmlPane.addHyperlinkListener(new HyperlinkListener() {
      public void hyperlinkUpdate(HyperlinkEvent e) {
	if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
	  try {
	    htmlPane.setPage(e.getURL());
	  } catch (IOException ioe) { System.out.println(ioe); }
	}
      }
    });

    
    //Add the scroll panes to a split pane.
    JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
    splitPane.setTopComponent(treeView);
    splitPane.setBottomComponent(htmlView);
    
    Dimension minimumSize = new Dimension(100, 50);
    htmlView.setMinimumSize(minimumSize);
    treeView.setMinimumSize(minimumSize);
    splitPane.setDividerLocation(100);
    splitPane.setPreferredSize(new Dimension(500, 300));
    
    //Add the split pane to this frame
    getContentPane().add(splitPane);
  }

  private class BookInfo {
    public String bookName;
    public URL bookURL;
    public String prefix = "http://"
                         + "www.cs.earlham.edu/~jimg/mozart/";

    public BookInfo(String book, String filename) {
      bookName = book;
      try {
	bookURL = new URL(prefix + filename);
      } catch (java.net.MalformedURLException exc) {
	System.err.println("Attempted to create a BookInfo "
			   + "with a bad URL: " + bookURL);
	bookURL = null;
      }
    }
    
    public String toString() {
      return bookName;
    }
  }
  
  private void initHelp() {
    String s = null;
    try {
      s = "file:" 
          + System.getProperty("user.dir")
          + System.getProperty("file.separator")
          + "TreeDemoHelp.html";
	  if (DEBUG) {
	    System.out.println("Help URL is " + s);
	  }
	  helpURL = new URL(s);
	  displayURL(helpURL);
    } catch (Exception e) {
      System.err.println("Couldn't create help URL: " + s);
    }
  }
  
  private void displayURL(URL url) {
    try {
      htmlPane.setPage(url);
    } catch (IOException e) {
      System.err.println("Attempted to read a bad URL: " + url);
    }
  }
  
  private void createNodes(DefaultMutableTreeNode top) {
    DefaultMutableTreeNode category = null;
    DefaultMutableTreeNode book = null;
    
    category = new DefaultMutableTreeNode("Mozart Specifications");
    top.add(category);
    
    //Tutorial
    book = new DefaultMutableTreeNode(new BookInfo
				      ("The Mozart Project Document",
				       "projectdoc.html"));
    category.add(book);
    
    //Arnold/Gosling
    book = new DefaultMutableTreeNode(new BookInfo
				      ("The Java Programming Language", "arnold.html"));
    category.add(book);
    
    //FAQ
    book = new DefaultMutableTreeNode(new BookInfo(
						   "The Java FAQ", "faq.html"));
    category.add(book);
    
    //Chan/Lee
    book = new DefaultMutableTreeNode(new BookInfo
				      ("The Java Class Libraries: An Annotated Reference",
				       "chanlee.html"));
    category.add(book);
    
    //Threads
    book = new DefaultMutableTreeNode(new BookInfo
				      ("Concurrent Programming in Java: Design Principles and Patterns",
				       "thread.html"));
    category.add(book);
    
    category = new DefaultMutableTreeNode("Books for Java Implementers");
    top.add(category);
    
    //VM
    book = new DefaultMutableTreeNode(new BookInfo
				      ("The Java Virtual Machine Specification",
				       "vm.html"));
    category.add(book);
    
    //Language Spec
    book = new DefaultMutableTreeNode(new BookInfo
				      ("The Java Language Specification",
				       "jls.html"));
    category.add(book);
  }
  
  public static void main(String[] args) {
    JFrame frame = new HelpBrowser();
    
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {System.exit(0);} 
    });  
    
    frame.pack();
    frame.setVisible(true);
  }
}
