[8579] | 1 | /**
|
---|
| 2 | *#########################################################################
|
---|
| 3 | *
|
---|
| 4 | * A component of the Gatherer application, part of the Greenstone digital
|
---|
| 5 | * library suite from the New Zealand Digital Library Project at the
|
---|
| 6 | * University of Waikato, New Zealand.
|
---|
| 7 | *
|
---|
| 8 | * <BR><BR>
|
---|
| 9 | *
|
---|
| 10 | * Principal Author: John Thompson, NZDL Project, University of Waikato
|
---|
| 11 | *
|
---|
| 12 | * <BR><BR>
|
---|
| 13 | *
|
---|
| 14 | * Copyright (C) 1999 New Zealand Digital Library Project
|
---|
| 15 | *
|
---|
| 16 | * <BR><BR>
|
---|
| 17 | *
|
---|
| 18 | * This program is free software; you can redistribute it and/or modify
|
---|
| 19 | * it under the terms of the GNU General Public License as published by
|
---|
| 20 | * the Free Software Foundation; either version 2 of the License, or
|
---|
| 21 | * (at your option) any later version.
|
---|
| 22 | *
|
---|
| 23 | * <BR><BR>
|
---|
| 24 | *
|
---|
| 25 | * This program is distributed in the hope that it will be useful,
|
---|
| 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 28 | * GNU General Public License for more details.
|
---|
| 29 | *
|
---|
| 30 | * <BR><BR>
|
---|
| 31 | *
|
---|
| 32 | * You should have received a copy of the GNU General Public License
|
---|
| 33 | * along with this program; if not, write to the Free Software
|
---|
| 34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
| 35 | *########################################################################
|
---|
| 36 | */
|
---|
| 37 | package org.greenstone.gatherer.gui;
|
---|
| 38 |
|
---|
| 39 | import java.awt.*;
|
---|
| 40 | import java.io.*;
|
---|
| 41 | import java.net.*;
|
---|
| 42 | import java.util.*;
|
---|
| 43 | import javax.swing.*;
|
---|
| 44 | import javax.swing.event.*;
|
---|
| 45 | import javax.swing.tree.*;
|
---|
[10009] | 46 | import org.greenstone.gatherer.Configuration;
|
---|
[8579] | 47 | import org.greenstone.gatherer.DebugStream;
|
---|
| 48 | import org.greenstone.gatherer.Dictionary;
|
---|
[10342] | 49 | import org.greenstone.gatherer.Gatherer;
|
---|
[10011] | 50 | import org.greenstone.gatherer.util.JarTools;
|
---|
[8579] | 51 | import org.greenstone.gatherer.util.StaticStrings;
|
---|
[10006] | 52 | import org.greenstone.gatherer.util.XMLTools;
|
---|
[8579] | 53 | import org.w3c.dom.*;
|
---|
| 54 |
|
---|
[10647] | 55 |
|
---|
[8579] | 56 | /**
|
---|
| 57 | * This class provides a nice help facility. It is a separate frame that can be positioned
|
---|
| 58 | * as the user wishes, and provides a contents page and the help information.
|
---|
| 59 | * @author Michael Dewsnip, NZDL Project
|
---|
| 60 | */
|
---|
| 61 | public class HelpFrame
|
---|
[10647] | 62 | extends JFrame
|
---|
| 63 | {
|
---|
[8579] | 64 | /** The size of the frame */
|
---|
[11033] | 65 | static private final Dimension SIZE = new Dimension(800, 560);
|
---|
[8579] | 66 |
|
---|
| 67 | static private HelpFrame self = null;
|
---|
| 68 |
|
---|
[10647] | 69 | /** The help view at the bottom of the frame. */
|
---|
| 70 | static private JEditorPane help_pane = null;
|
---|
| 71 | /** The help contents tree at the top of the frame. */
|
---|
| 72 | static private JTree help_contents_tree = null;
|
---|
| 73 | /** The help contents tree model. */
|
---|
| 74 | static private HelpContentsTreeModel help_contents_tree_model = null;
|
---|
| 75 | /** The split between the contents tree and the page view. */
|
---|
| 76 | static private JSplitPane split_pane = null;
|
---|
[8579] | 77 |
|
---|
| 78 | public HelpFrame()
|
---|
| 79 | {
|
---|
| 80 | setDefaultCloseOperation(HIDE_ON_CLOSE);
|
---|
| 81 | setSize(SIZE);
|
---|
[12119] | 82 | setTitle(Dictionary.get("Help.Title"));
|
---|
[18370] | 83 | this.setComponentOrientation(Dictionary.getOrientation());
|
---|
| 84 |
|
---|
[10647] | 85 | help_pane = new JEditorPane();
|
---|
[18370] | 86 | help_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
[10647] | 87 | help_pane.setEditable(false);
|
---|
| 88 | help_pane.addHyperlinkListener(new HelpPaneHyperlinkListener());
|
---|
[8579] | 89 |
|
---|
[10647] | 90 | HelpContentsTreeNode help_tree_root_node = new HelpContentsTreeNode(null, Dictionary.get("Help.Contents"));
|
---|
| 91 | help_contents_tree_model = new HelpContentsTreeModel(help_tree_root_node);
|
---|
| 92 | help_contents_tree = new JTree((DefaultTreeModel) help_contents_tree_model);
|
---|
[18370] | 93 | help_contents_tree.setComponentOrientation(Dictionary.getOrientation());
|
---|
[10647] | 94 | help_contents_tree.addTreeSelectionListener(new HelpContentsTreeSelectionListener());
|
---|
| 95 | help_contents_tree.setExpandsSelectedPaths(true);
|
---|
[8579] | 96 |
|
---|
| 97 | // Creation
|
---|
| 98 | JPanel content_pane = (JPanel) this.getContentPane();
|
---|
[18370] | 99 | content_pane.setComponentOrientation(Dictionary.getOrientation());
|
---|
| 100 | split_pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
---|
[10647] | 101 | JScrollPane help_contents_tree_scroll = new JScrollPane(help_contents_tree);
|
---|
[18370] | 102 | help_contents_tree_scroll.setComponentOrientation(Dictionary.getOrientation());
|
---|
[10647] | 103 | JScrollPane help_pane_scroll = new JScrollPane(help_pane);
|
---|
[18370] | 104 | help_pane_scroll.setComponentOrientation(Dictionary.getOrientation());
|
---|
[8579] | 105 |
|
---|
| 106 | // Layout
|
---|
[18370] | 107 | if (Dictionary.getOrientation().isLeftToRight()){
|
---|
| 108 | split_pane.add(help_contents_tree_scroll, JSplitPane.LEFT);
|
---|
| 109 | split_pane.add(help_pane_scroll, JSplitPane.RIGHT);
|
---|
| 110 | }else{
|
---|
| 111 | split_pane.add(help_contents_tree_scroll, JSplitPane.RIGHT);
|
---|
| 112 | split_pane.add(help_pane_scroll, JSplitPane.LEFT);
|
---|
| 113 | }
|
---|
| 114 |
|
---|
[8579] | 115 | content_pane.setLayout(new BorderLayout());
|
---|
| 116 | content_pane.add(split_pane, BorderLayout.CENTER);
|
---|
| 117 |
|
---|
| 118 | // Center
|
---|
| 119 | Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
|
---|
| 120 | setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
|
---|
| 121 |
|
---|
[17916] | 122 |
|
---|
[8579] | 123 | // Pretty corner icon
|
---|
[22683] | 124 | String gsmall_image = "gatherer.png";
|
---|
[17916] | 125 | if (Configuration.fedora_info.isActive()) {
|
---|
| 126 | gsmall_image = "fli-" + gsmall_image;
|
---|
| 127 | }
|
---|
[8579] | 128 |
|
---|
[17916] | 129 | this.setIconImage(JarTools.getImage(gsmall_image).getImage());
|
---|
| 130 |
|
---|
[8579] | 131 | self = this;
|
---|
| 132 | }
|
---|
| 133 |
|
---|
| 134 | public void destroy()
|
---|
| 135 | {
|
---|
[10647] | 136 | help_contents_tree = null;
|
---|
| 137 | help_pane = null;
|
---|
[8579] | 138 | }
|
---|
| 139 |
|
---|
| 140 |
|
---|
[10647] | 141 | /** Retrieve the relative file path to the language-specific help index xml file. */
|
---|
[10009] | 142 | private String getHelpFolder()
|
---|
| 143 | {
|
---|
| 144 | String help_folder = "help/" + Configuration.getLanguage() + "/";
|
---|
| 145 |
|
---|
[10647] | 146 | // Applet case: get help files out of JAR file
|
---|
| 147 | if (Gatherer.isApplet && JarTools.getResource("/" + help_folder) != null) {
|
---|
[10009] | 148 | return help_folder;
|
---|
| 149 | }
|
---|
| 150 |
|
---|
[10647] | 151 | // Normal case: get help files out of GLI "help" folder
|
---|
| 152 | if (new File(help_folder).exists()) {
|
---|
[10009] | 153 | return help_folder;
|
---|
| 154 | }
|
---|
| 155 |
|
---|
| 156 | // Resort to English
|
---|
| 157 | return "help/" + StaticStrings.ENGLISH_LANGUAGE_STR + "/";
|
---|
| 158 | }
|
---|
| 159 |
|
---|
| 160 |
|
---|
[10647] | 161 | private URL getURLForSection(String section_name)
|
---|
| 162 | {
|
---|
| 163 | // Form the path to the help file from the section name
|
---|
| 164 | if (section_name != null) {
|
---|
| 165 | String help_file_path = getHelpFolder() + section_name + StaticStrings.HTM_FILE_EXTENSION;
|
---|
| 166 |
|
---|
| 167 | try {
|
---|
| 168 | // Applet case: get help file out of JAR file
|
---|
| 169 | if (Gatherer.isApplet) {
|
---|
| 170 | return JarTools.getResource("/" + help_file_path);
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | // Normal case: get help file out of GLI "help" folder
|
---|
[18715] | 174 | return (new File(help_file_path)).toURI().toURL();
|
---|
[10647] | 175 | }
|
---|
| 176 | catch (Exception exception) {
|
---|
| 177 | DebugStream.printStackTrace(exception);
|
---|
| 178 | }
|
---|
| 179 | }
|
---|
| 180 |
|
---|
| 181 | return null;
|
---|
| 182 | }
|
---|
| 183 |
|
---|
| 184 |
|
---|
| 185 | static private void selectHelpContentsTreeNode(String section_name)
|
---|
| 186 | {
|
---|
| 187 | // Find the tree node with this section name, then select it
|
---|
| 188 | selectHelpContentsTreeNode(help_contents_tree_model.getHelpContentsTreeNodeNamed(section_name));
|
---|
| 189 | }
|
---|
| 190 |
|
---|
| 191 |
|
---|
| 192 | static private void selectHelpContentsTreeNode(HelpContentsTreeNode help_tree_node)
|
---|
| 193 | {
|
---|
| 194 | // Ensure the node in the help contents tree is selected and visible
|
---|
| 195 | TreePath help_tree_node_path = new TreePath(help_tree_node.getPath());
|
---|
| 196 | help_contents_tree.setSelectionPath(help_tree_node_path);
|
---|
| 197 | help_contents_tree.scrollPathToVisible(help_tree_node_path);
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 |
|
---|
[8579] | 201 | static public void setView(String section_name)
|
---|
| 202 | {
|
---|
[10647] | 203 | // Select the appropriate node in the help contents tree
|
---|
| 204 | selectHelpContentsTreeNode(section_name);
|
---|
| 205 |
|
---|
| 206 | // Show the help page with the specified section name
|
---|
| 207 | self.showHelpPage(section_name);
|
---|
[8579] | 208 | }
|
---|
| 209 |
|
---|
| 210 |
|
---|
[10647] | 211 | private void showHelpPage(String section_name)
|
---|
[8579] | 212 | {
|
---|
[10647] | 213 | // Find the tree node with this section name, then show the page for the node
|
---|
| 214 | showHelpPage(getURLForSection(section_name));
|
---|
| 215 | }
|
---|
[8579] | 216 |
|
---|
| 217 |
|
---|
[10647] | 218 | private void showHelpPage(URL help_page_url)
|
---|
| 219 | {
|
---|
[8579] | 220 | // Display the selected page
|
---|
[10647] | 221 | if (help_page_url != null) {
|
---|
[8579] | 222 | try {
|
---|
[10647] | 223 | help_pane.setPage(help_page_url);
|
---|
[8579] | 224 | }
|
---|
| 225 | catch (Exception exception) {
|
---|
| 226 | DebugStream.printStackTrace(exception);
|
---|
| 227 | }
|
---|
| 228 | }
|
---|
| 229 |
|
---|
| 230 | // Make the help frame visible
|
---|
| 231 | setVisible(true);
|
---|
[11033] | 232 | split_pane.setDividerLocation(0.4);
|
---|
[8579] | 233 | }
|
---|
| 234 |
|
---|
| 235 |
|
---|
[10647] | 236 | private class HelpContentsTreeModel
|
---|
| 237 | extends DefaultTreeModel
|
---|
| 238 | {
|
---|
| 239 | public HelpContentsTreeModel(MutableTreeNode help_tree_root_node)
|
---|
| 240 | {
|
---|
| 241 | super(help_tree_root_node);
|
---|
[8579] | 242 |
|
---|
[10647] | 243 | // Load the XML help index file and build the contents structure from it
|
---|
[8579] | 244 | try {
|
---|
[10647] | 245 | String help_index_file_path = getHelpFolder() + "help_index.xml";
|
---|
[16333] | 246 | Document document = null;
|
---|
| 247 | if (Gatherer.isApplet && JarTools.getResource(help_index_file_path) != null) {
|
---|
| 248 | document = XMLTools.parseXMLFile(help_index_file_path, true);
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 | if (new File(help_index_file_path).exists()) {
|
---|
| 252 | document = XMLTools.parseXMLFile(help_index_file_path, false);
|
---|
| 253 | }
|
---|
[8579] | 254 |
|
---|
[17005] | 255 | if (document == null) {
|
---|
| 256 | String errormsg = "HelpFrame.HelpContentsTreeModel constructor(): There's no help document after parsing";
|
---|
| 257 | System.err.println(errormsg);
|
---|
| 258 | DebugStream.println(errormsg);
|
---|
| 259 | return;
|
---|
| 260 | }
|
---|
[10647] | 261 | // Traverse the help hierarchy, building a tree representing its structure
|
---|
| 262 | Node document_node = document.getFirstChild();
|
---|
[8579] | 263 |
|
---|
[10647] | 264 | // Add a help contents tree node for each major section
|
---|
| 265 | int section_number = 0;
|
---|
| 266 | NodeList children = document_node.getChildNodes();
|
---|
[8579] | 267 | for (int i = 0; i < children.getLength(); i++) {
|
---|
| 268 | Node child = children.item(i);
|
---|
| 269 | if (child.getNodeName().equals(StaticStrings.SECTION_ELEMENT)) {
|
---|
[10647] | 270 | section_number++;
|
---|
| 271 | buildHelpContentsTree(help_tree_root_node, section_number + StaticStrings.EMPTY_STR, child);
|
---|
[8579] | 272 | }
|
---|
| 273 | }
|
---|
| 274 | }
|
---|
[10647] | 275 | catch (Exception exception) {
|
---|
| 276 | DebugStream.printStackTrace(exception);
|
---|
[8579] | 277 | }
|
---|
| 278 | }
|
---|
| 279 |
|
---|
| 280 |
|
---|
[10647] | 281 | private void buildHelpContentsTree(MutableTreeNode parent, String pos, Node node)
|
---|
[8579] | 282 | {
|
---|
| 283 | // Determine the section name
|
---|
[10647] | 284 | String section_name = ((Element) node).getAttribute(StaticStrings.NAME_ATTRIBUTE);
|
---|
[8579] | 285 |
|
---|
| 286 | // Determine the section title
|
---|
[10647] | 287 | String section_title = "";
|
---|
[8579] | 288 | NodeList children = node.getChildNodes();
|
---|
| 289 | for (int i = 0; i < children.getLength(); i++) {
|
---|
| 290 | Node child = children.item(i);
|
---|
| 291 | if (child.getNodeName().equals(StaticStrings.TITLE_ELEMENT)) {
|
---|
[10647] | 292 | section_title = pos + ": ";
|
---|
[8579] | 293 | if (child.getFirstChild() != null) {
|
---|
[10647] | 294 | section_title += child.getFirstChild().getNodeValue();
|
---|
[8579] | 295 | }
|
---|
| 296 | }
|
---|
| 297 | }
|
---|
| 298 |
|
---|
| 299 | // Add the node into the tree
|
---|
[10647] | 300 | HelpContentsTreeNode help_tree_node = new HelpContentsTreeNode(section_name, section_title);
|
---|
| 301 | insertNodeInto(help_tree_node, parent, parent.getChildCount());
|
---|
[8579] | 302 |
|
---|
| 303 | // Apply recursively to the children of this node
|
---|
[10647] | 304 | int section_number = 0;
|
---|
[8579] | 305 | for (int i = 0; i < children.getLength(); i++) {
|
---|
| 306 | Node child = children.item(i);
|
---|
| 307 | if (child.getNodeName().equals(StaticStrings.SECTION_ELEMENT)) {
|
---|
[10647] | 308 | section_number++;
|
---|
| 309 | buildHelpContentsTree(help_tree_node, pos + StaticStrings.STOP_CHARACTER + section_number, child);
|
---|
[8579] | 310 | }
|
---|
| 311 | }
|
---|
| 312 | }
|
---|
| 313 |
|
---|
| 314 |
|
---|
[10647] | 315 | private HelpContentsTreeNode getHelpContentsTreeNodeNamed(String section_name)
|
---|
[8579] | 316 | {
|
---|
[10647] | 317 | // Find the node with name matching section name, somewhere in the tree
|
---|
| 318 | if (section_name != null) {
|
---|
| 319 | Enumeration descendants = ((DefaultMutableTreeNode) root).preorderEnumeration();
|
---|
| 320 | while (descendants.hasMoreElements()) {
|
---|
| 321 | HelpContentsTreeNode help_tree_node = (HelpContentsTreeNode) descendants.nextElement();
|
---|
| 322 | if (section_name.equals(help_tree_node.section_name)) {
|
---|
| 323 | return help_tree_node;
|
---|
| 324 | }
|
---|
[8579] | 325 | }
|
---|
| 326 | }
|
---|
| 327 |
|
---|
| 328 | // Couldn't be found, so just return the root (Contents) node
|
---|
[10647] | 329 | return (HelpContentsTreeNode) root;
|
---|
[8579] | 330 | }
|
---|
| 331 | }
|
---|
| 332 |
|
---|
| 333 |
|
---|
| 334 | /** This listener is used to listen for selection changes in the contents tree, and
|
---|
| 335 | * to show the appropriate page as required.
|
---|
| 336 | */
|
---|
[10647] | 337 | private class HelpContentsTreeSelectionListener
|
---|
| 338 | implements TreeSelectionListener
|
---|
| 339 | {
|
---|
[8579] | 340 | /** Any implementation of <i>TreeSelectionListener</i> must include this method so we can be informed when the tree selection changes.
|
---|
| 341 | * @param event A <strong>TreeSelectionEvent</strong> containing al the relevant information about the event itself.
|
---|
| 342 | */
|
---|
| 343 | public void valueChanged(TreeSelectionEvent event)
|
---|
| 344 | {
|
---|
[10647] | 345 | HelpContentsTreeNode help_tree_node = (HelpContentsTreeNode) event.getPath().getLastPathComponent();
|
---|
| 346 | selectHelpContentsTreeNode(help_tree_node);
|
---|
| 347 | showHelpPage(help_tree_node.section_name);
|
---|
[8579] | 348 | }
|
---|
| 349 | }
|
---|
| 350 |
|
---|
| 351 |
|
---|
| 352 | /** This class provides a wrapper around a <strong>DefaultMutableTreeNode</strong> which
|
---|
| 353 | * provides the ability to set an html page to be loaded when this node is selected.
|
---|
| 354 | */
|
---|
[10647] | 355 | private class HelpContentsTreeNode
|
---|
| 356 | extends DefaultMutableTreeNode
|
---|
| 357 | {
|
---|
[8579] | 358 | /** The unique name of the section (matches the HTML filename) */
|
---|
[10647] | 359 | public String section_name = null;
|
---|
[8579] | 360 | /** The title to be displayed for this tree node. */
|
---|
[10647] | 361 | public String section_title = null;
|
---|
[8579] | 362 |
|
---|
[10647] | 363 | public HelpContentsTreeNode(String section_name, String section_title)
|
---|
[8579] | 364 | {
|
---|
[10647] | 365 | this.section_name = section_name;
|
---|
| 366 | this.section_title = section_title;
|
---|
[8579] | 367 | }
|
---|
| 368 |
|
---|
| 369 | public String toString()
|
---|
| 370 | {
|
---|
[10647] | 371 | return section_title;
|
---|
[8579] | 372 | }
|
---|
| 373 | }
|
---|
| 374 |
|
---|
| 375 |
|
---|
[10647] | 376 | private class HelpPaneHyperlinkListener
|
---|
| 377 | implements HyperlinkListener
|
---|
| 378 | {
|
---|
| 379 | public void hyperlinkUpdate(HyperlinkEvent e)
|
---|
| 380 | {
|
---|
| 381 | if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
---|
| 382 | // Determine which node in the help contents tree to select, then select it
|
---|
| 383 | String section_link = e.getURL().getFile();
|
---|
| 384 | if (section_link.endsWith(".htm")) {
|
---|
| 385 | section_link = section_link.substring(section_link.lastIndexOf("/") + 1);
|
---|
| 386 | section_link = section_link.substring(0, section_link.length() - ".htm".length());
|
---|
| 387 | selectHelpContentsTreeNode(section_link);
|
---|
[8579] | 388 | }
|
---|
[10647] | 389 |
|
---|
| 390 | // Change to the page specified by the link
|
---|
| 391 | showHelpPage(e.getURL());
|
---|
[8579] | 392 | }
|
---|
| 393 | }
|
---|
| 394 | }
|
---|
| 395 | }
|
---|