/**
*#########################################################################
*
* A component of the Gatherer application, part of the Greenstone digital
* library suite from the New Zealand Digital Library Project at the
* University of Waikato, New Zealand.
*
*
*
* Principal Author: John Thompson, NZDL Project, University of Waikato
*
*
*
* Copyright (C) 1999 New Zealand Digital Library Project
*
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
*
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*########################################################################
*/
package org.greenstone.gatherer.gui;
import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.DebugStream;
import org.greenstone.gatherer.Dictionary;
import org.greenstone.gatherer.Gatherer;
import org.greenstone.gatherer.util.JarTools;
import org.greenstone.gatherer.util.StaticStrings;
import org.greenstone.gatherer.util.XMLTools;
import org.w3c.dom.*;
/**
* This class provides a nice help facility. It is a separate frame that can be positioned
* as the user wishes, and provides a contents page and the help information.
* @author Michael Dewsnip, NZDL Project
*/
public class HelpFrame
extends JFrame
{
/** The size of the frame */
static private final Dimension SIZE = new Dimension(800, 560);
static private HelpFrame self = null;
/** The help view at the bottom of the frame. */
static private JEditorPane help_pane = null;
/** The help contents tree at the top of the frame. */
static private JTree help_contents_tree = null;
/** The help contents tree model. */
static private HelpContentsTreeModel help_contents_tree_model = null;
/** The split between the contents tree and the page view. */
static private JSplitPane split_pane = null;
public HelpFrame()
{
setDefaultCloseOperation(HIDE_ON_CLOSE);
setSize(SIZE);
setTitle(Dictionary.get("Help.Title"));
help_pane = new JEditorPane();
help_pane.setEditable(false);
help_pane.addHyperlinkListener(new HelpPaneHyperlinkListener());
HelpContentsTreeNode help_tree_root_node = new HelpContentsTreeNode(null, Dictionary.get("Help.Contents"));
help_contents_tree_model = new HelpContentsTreeModel(help_tree_root_node);
help_contents_tree = new JTree((DefaultTreeModel) help_contents_tree_model);
help_contents_tree.addTreeSelectionListener(new HelpContentsTreeSelectionListener());
help_contents_tree.setExpandsSelectedPaths(true);
// Creation
JPanel content_pane = (JPanel) this.getContentPane();
split_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JScrollPane help_contents_tree_scroll = new JScrollPane(help_contents_tree);
JScrollPane help_pane_scroll = new JScrollPane(help_pane);
// Layout
split_pane.add(help_contents_tree_scroll, JSplitPane.LEFT);
split_pane.add(help_pane_scroll, JSplitPane.RIGHT);
content_pane.setLayout(new BorderLayout());
content_pane.add(split_pane, BorderLayout.CENTER);
// Center
Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
// Pretty corner icon
this.setIconImage(JarTools.getImage("gatherer_small.gif").getImage());
self = this;
}
public void destroy()
{
help_contents_tree = null;
help_pane = null;
}
/** Retrieve the relative file path to the language-specific help index xml file. */
private String getHelpFolder()
{
String help_folder = "help/" + Configuration.getLanguage() + "/";
// Applet case: get help files out of JAR file
if (Gatherer.isApplet && JarTools.getResource("/" + help_folder) != null) {
return help_folder;
}
// Normal case: get help files out of GLI "help" folder
if (new File(help_folder).exists()) {
return help_folder;
}
// Resort to English
return "help/" + StaticStrings.ENGLISH_LANGUAGE_STR + "/";
}
private URL getURLForSection(String section_name)
{
// Form the path to the help file from the section name
if (section_name != null) {
String help_file_path = getHelpFolder() + section_name + StaticStrings.HTM_FILE_EXTENSION;
try {
// Applet case: get help file out of JAR file
if (Gatherer.isApplet) {
return JarTools.getResource("/" + help_file_path);
}
// Normal case: get help file out of GLI "help" folder
return (new File(help_file_path)).toURL();
}
catch (Exception exception) {
DebugStream.printStackTrace(exception);
}
}
return null;
}
static private void selectHelpContentsTreeNode(String section_name)
{
// Find the tree node with this section name, then select it
selectHelpContentsTreeNode(help_contents_tree_model.getHelpContentsTreeNodeNamed(section_name));
}
static private void selectHelpContentsTreeNode(HelpContentsTreeNode help_tree_node)
{
// Ensure the node in the help contents tree is selected and visible
TreePath help_tree_node_path = new TreePath(help_tree_node.getPath());
help_contents_tree.setSelectionPath(help_tree_node_path);
help_contents_tree.scrollPathToVisible(help_tree_node_path);
}
static public void setView(String section_name)
{
// Select the appropriate node in the help contents tree
selectHelpContentsTreeNode(section_name);
// Show the help page with the specified section name
self.showHelpPage(section_name);
}
private void showHelpPage(String section_name)
{
// Find the tree node with this section name, then show the page for the node
showHelpPage(getURLForSection(section_name));
}
private void showHelpPage(URL help_page_url)
{
// Display the selected page
if (help_page_url != null) {
try {
help_pane.setPage(help_page_url);
}
catch (Exception exception) {
DebugStream.printStackTrace(exception);
}
}
// Make the help frame visible
setVisible(true);
split_pane.setDividerLocation(0.4);
}
private class HelpContentsTreeModel
extends DefaultTreeModel
{
public HelpContentsTreeModel(MutableTreeNode help_tree_root_node)
{
super(help_tree_root_node);
// Load the XML help index file and build the contents structure from it
try {
String help_index_file_path = getHelpFolder() + "help_index.xml";
Document document = XMLTools.parseXMLFile(help_index_file_path, true);
// Traverse the help hierarchy, building a tree representing its structure
Node document_node = document.getFirstChild();
// Add a help contents tree node for each major section
int section_number = 0;
NodeList children = document_node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equals(StaticStrings.SECTION_ELEMENT)) {
section_number++;
buildHelpContentsTree(help_tree_root_node, section_number + StaticStrings.EMPTY_STR, child);
}
}
}
catch (Exception exception) {
DebugStream.printStackTrace(exception);
}
}
private void buildHelpContentsTree(MutableTreeNode parent, String pos, Node node)
{
// Determine the section name
String section_name = ((Element) node).getAttribute(StaticStrings.NAME_ATTRIBUTE);
// Determine the section title
String section_title = "";
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equals(StaticStrings.TITLE_ELEMENT)) {
section_title = pos + ": ";
if (child.getFirstChild() != null) {
section_title += child.getFirstChild().getNodeValue();
}
}
}
// Add the node into the tree
HelpContentsTreeNode help_tree_node = new HelpContentsTreeNode(section_name, section_title);
insertNodeInto(help_tree_node, parent, parent.getChildCount());
// Apply recursively to the children of this node
int section_number = 0;
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
if (child.getNodeName().equals(StaticStrings.SECTION_ELEMENT)) {
section_number++;
buildHelpContentsTree(help_tree_node, pos + StaticStrings.STOP_CHARACTER + section_number, child);
}
}
}
private HelpContentsTreeNode getHelpContentsTreeNodeNamed(String section_name)
{
// Find the node with name matching section name, somewhere in the tree
if (section_name != null) {
Enumeration descendants = ((DefaultMutableTreeNode) root).preorderEnumeration();
while (descendants.hasMoreElements()) {
HelpContentsTreeNode help_tree_node = (HelpContentsTreeNode) descendants.nextElement();
if (section_name.equals(help_tree_node.section_name)) {
return help_tree_node;
}
}
}
// Couldn't be found, so just return the root (Contents) node
return (HelpContentsTreeNode) root;
}
}
/** This listener is used to listen for selection changes in the contents tree, and
* to show the appropriate page as required.
*/
private class HelpContentsTreeSelectionListener
implements TreeSelectionListener
{
/** Any implementation of TreeSelectionListener must include this method so we can be informed when the tree selection changes.
* @param event A TreeSelectionEvent containing al the relevant information about the event itself.
*/
public void valueChanged(TreeSelectionEvent event)
{
HelpContentsTreeNode help_tree_node = (HelpContentsTreeNode) event.getPath().getLastPathComponent();
selectHelpContentsTreeNode(help_tree_node);
showHelpPage(help_tree_node.section_name);
}
}
/** This class provides a wrapper around a DefaultMutableTreeNode which
* provides the ability to set an html page to be loaded when this node is selected.
*/
private class HelpContentsTreeNode
extends DefaultMutableTreeNode
{
/** The unique name of the section (matches the HTML filename) */
public String section_name = null;
/** The title to be displayed for this tree node. */
public String section_title = null;
public HelpContentsTreeNode(String section_name, String section_title)
{
this.section_name = section_name;
this.section_title = section_title;
}
public String toString()
{
return section_title;
}
}
private class HelpPaneHyperlinkListener
implements HyperlinkListener
{
public void hyperlinkUpdate(HyperlinkEvent e)
{
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
// Determine which node in the help contents tree to select, then select it
String section_link = e.getURL().getFile();
if (section_link.endsWith(".htm")) {
section_link = section_link.substring(section_link.lastIndexOf("/") + 1);
section_link = section_link.substring(0, section_link.length() - ".htm".length());
selectHelpContentsTreeNode(section_link);
}
// Change to the page specified by the link
showHelpPage(e.getURL());
}
}
}
}