/** *######################################################################### * * 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")); this.setComponentOrientation(Dictionary.getOrientation()); help_pane = new JEditorPane(); help_pane.setComponentOrientation(Dictionary.getOrientation()); 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.setComponentOrientation(Dictionary.getOrientation()); help_contents_tree.addTreeSelectionListener(new HelpContentsTreeSelectionListener()); help_contents_tree.setExpandsSelectedPaths(true); // Creation JPanel content_pane = (JPanel) this.getContentPane(); content_pane.setComponentOrientation(Dictionary.getOrientation()); split_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); JScrollPane help_contents_tree_scroll = new JScrollPane(help_contents_tree); help_contents_tree_scroll.setComponentOrientation(Dictionary.getOrientation()); JScrollPane help_pane_scroll = new JScrollPane(help_pane); help_pane_scroll.setComponentOrientation(Dictionary.getOrientation()); // Layout if (Dictionary.getOrientation().isLeftToRight()){ split_pane.add(help_contents_tree_scroll, JSplitPane.LEFT); split_pane.add(help_pane_scroll, JSplitPane.RIGHT); }else{ split_pane.add(help_contents_tree_scroll, JSplitPane.RIGHT); split_pane.add(help_pane_scroll, JSplitPane.LEFT); } 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 String gsmall_image = "gatherer.png"; if (Configuration.fedora_info.isActive()) { gsmall_image = "fli-" + gsmall_image; } this.setIconImage(JarTools.getImage(gsmall_image).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)).toURI().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 = null; if (Gatherer.isApplet && JarTools.getResource(help_index_file_path) != null) { document = XMLTools.parseXMLFile(help_index_file_path, true); } if (new File(help_index_file_path).exists()) { document = XMLTools.parseXMLFile(help_index_file_path, false); } if (document == null) { String errormsg = "HelpFrame.HelpContentsTreeModel constructor(): There's no help document after parsing"; System.err.println(errormsg); DebugStream.println(errormsg); return; } // 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()); } } } }