4 * Created on 09 November 2001, 16:13
\r
5 * $Header: /VisTA/CID/Components/xhtmlHelp.java 7 12/11/01 3:01 Tj $
\r
7 * $History: xhtmlHelp.java $
\r
9 * ***************** Version 7 *****************
\r
10 * User: Tj Date: 12/11/01 Time: 3:01
\r
11 * Updated in $/VisTA/CID/Components
\r
12 * Added History List logic to prevent duplicate titles. Added
\r
13 * setLookAndFeel(), added L&F resize control logic
\r
15 * ***************** Version 6 *****************
\r
16 * User: Tj Date: 11/11/01 Time: 4:10
\r
17 * Updated in $/VisTA/CID/Components
\r
18 * Added Back, Forward, Refresh functionality. Added Online button.
\r
20 * ***************** Version 5 *****************
\r
21 * User: Tj Date: 11/11/01 Time: 0:07
\r
22 * Updated in $/VisTA/CID/Components
\r
23 * Added setPage(URL) and detection of local help versus external pages
\r
24 * (for locale-sensitive page selection)
\r
26 * ***************** Version 4 *****************
\r
27 * User: Tj Date: 10/11/01 Time: 2:20
\r
28 * Updated in $/VisTA/CID
\r
29 * Added alternate <title> or <el id=title> Document Title detection
\r
31 * ***************** Version 3 *****************
\r
32 * User: Tj Date: 10/11/01 Time: 1:37
\r
33 * Updated in $/VisTA/CID
\r
34 * Added: dynamic Locale-sensitive support, window icon, history-combo
\r
35 * lists DocTitle, refresh is locale-sensitive
\r
37 * ***************** Version 2 *****************
\r
38 * User: Tj Date: 9/11/01 Time: 21:06
\r
39 * Updated in $/VisTA/CID
\r
40 * Added support for URL History
\r
42 package org.tjworld.components;
\r
44 import java.awt.Color;
\r
45 import java.awt.Component;
\r
46 import java.awt.Cursor;
\r
47 import java.awt.Dimension;
\r
48 import java.awt.Point;
\r
50 import java.io.IOException;
\r
51 import java.net.URL;
\r
52 import java.util.Locale;
\r
53 import java.util.Vector;
\r
55 import javax.swing.UIManager;
\r
56 import javax.swing.JEditorPane;
\r
57 import javax.swing.JTree;
\r
58 import javax.swing.ComboBoxModel;
\r
59 import javax.swing.ImageIcon;
\r
60 import javax.swing.SwingUtilities;
\r
61 import javax.swing.UIManager;
\r
62 import javax.swing.UnsupportedLookAndFeelException;
\r
63 import javax.swing.event.DocumentListener;
\r
64 import javax.swing.event.DocumentEvent;
\r
65 import javax.swing.event.HyperlinkEvent;
\r
66 import javax.swing.event.HyperlinkListener;
\r
67 import javax.swing.event.TreeSelectionListener;
\r
68 import javax.swing.event.TreeSelectionEvent;
\r
69 import javax.swing.text.Document;
\r
70 import javax.swing.text.html.HTML;
\r
71 import javax.swing.text.html.HTMLDocument;
\r
72 import javax.swing.text.html.HTMLFrameHyperlinkEvent;
\r
73 import javax.swing.tree.TreeModel;
\r
74 import javax.swing.tree.TreeSelectionModel;
\r
75 import javax.swing.tree.DefaultMutableTreeNode;
\r
77 import org.tjworld.vista.cid.VistaFilter;
\r
79 import java.io.InputStream;
\r
80 import java.io.IOException;
\r
81 import java.net.HttpURLConnection;
\r
82 import java.net.URLConnection;
\r
83 import javax.swing.text.html.HTMLEditorKit;
\r
87 * Hopefully entitled xhtml, unfortunately the standard JTextPane models cannot support more than
\r
88 * HTML 3.2 or 4.0, depending on the documentation/source code comments.
\r
90 * Provides a Locale-sensitive help service with a toolbar and split-pane window.
\r
91 * Toolbar provides common browser buttons and a History ComboBox. To the left of the split pane is
\r
92 * a Navigation pane with three tabs: Contents, (searchable) Index, and Search (all text).
\r
93 * The right pane contains the current help document.
\r
96 * @version 1.0 10 Nov, 2001
\r
98 public class xhtmlHelp extends javax.swing.JFrame implements HyperlinkListener, TreeSelectionListener {
\r
99 private URL helpBase = null;
\r
100 private String defaultLanguage = "en";
\r
101 private String language = "en";
\r
102 private String country = "GB";
\r
103 private boolean pageLoaded = false;
\r
104 private boolean manualPosition = false;
\r
105 private boolean inExtMove = false;
\r
106 private boolean docking = false;
\r
108 /** default glass pane before being replaced by VisTA filter */
\r
109 private Component defaultGlassPane;
\r
111 /** VisTA colourized transparent filter pane */
\r
112 private VistaFilter vfFilter;
\r
114 private String currentPage = null;
\r
115 /** frame's small icon */
\r
116 private ImageIcon icHelp;
\r
118 /** Creates new form xhtmlHelp */
\r
119 public xhtmlHelp() {
\r
120 this((URL)null, (Locale)null, (String)null);
\r
123 /** Creates a new xhtml with initial HTML page
\r
124 * @param base The URL where the help files are located
\r
125 * @param loc The Locale used by the help system
\r
126 * @param initialPage The first page to display. A simple filename.extension, no path (unless the
\r
127 * path part is relative to the Locale-specfic directory)
\r
129 * base might be created using: new URL(myAppURL, "help/")
\r
131 public xhtmlHelp(URL base, Locale loc, String initialPage) {
\r
132 /* don't use the Host window decoration if at all possible
\r
133 * Must do this before the frame becomes Displayable
\r
134 * (by a call to pack() or show() )
\r
136 if(UIManager.getLookAndFeel().getSupportsWindowDecorations()) {
\r
137 setUndecorated(true);
\r
138 getRootPane().setWindowDecorationStyle(javax.swing.JRootPane.FRAME);
\r
141 icHelp = new ImageIcon(getClass().getResource("/org/tjworld/components/media/help.gif"));
\r
143 contentsTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
\r
144 indexTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
\r
146 contentsTree.addTreeSelectionListener(this);
\r
147 indexTree.addTreeSelectionListener(this);
\r
149 lstHistory.setRenderer(new IconTitledURLItemRenderer());
\r
151 if(loc == null) loc = Locale.getDefault();
\r
152 setPageLocale(loc);
\r
155 } catch(Exception e) {
\r
158 setPage(initialPage);
\r
159 helpDoc.addHyperlinkListener(this);
\r
161 // configure the VisTA filter
\r
162 vfFilter = new VistaFilter();
\r
163 vfFilter.setAlpha(0.5f); // transparency is a decimal between 0.0 and 1.0
\r
164 vfFilter.setBackground(Color.blue); //*** might want to have this set from saved Personal Preferences later
\r
166 // prepare for taking over the Frame's glass pane too
\r
167 defaultGlassPane = getGlassPane(); // keep track so it can be swapped in and out
\r
168 setGlassPane(vfFilter); // replace it with the filter
\r
171 private boolean vistaFilterOn = false;
\r
173 public boolean isVista() {
\r
174 return vistaFilterOn;
\r
177 public void setVista(boolean enable) {
\r
178 vistaFilterOn = enable;
\r
179 vfFilter.setVisible(vistaFilterOn);
\r
182 public void setVistaColour(Color c, float alpha) {
\r
183 if(c != null) vfFilter.setBackground(c);
\r
184 vfFilter.setAlpha(alpha);
\r
187 public Color getVistaColor(Float alpha) {
\r
188 alpha = new Float(vfFilter.getAlpha());
\r
189 return vfFilter.getBackground();
\r
192 /** Sets the locale to use in displaying help files
\r
194 * When a page is already loaded, a change of Locale will cause the the new Locale's version
\r
195 * of this page to be loaded, if there is one.
\r
198 * If /help/en/default.html is loaded when setPageLocale(Locale.CANADA_FRENCH) is called,
\r
199 * /help/fr/CA/default.html will be looked for first, if not found, then
\r
200 * /help/fr/default.html will be looked for, if not found then
\r
201 * /help/en/default.html will be looked for, where "en" is the default Locale language
\r
202 * @param loc The new currentLocale
\r
204 public void setPageLocale(Locale loc) {
\r
205 if(loc != null) language = loc.getLanguage(); // get the ISO-639 language code, to make a directory name
\r
206 if(loc != null) country = loc.getCountry(); // get the ISO-3166 2-letter coode, to make a directory name
\r
211 /** Determine if a page is currently displayed
\r
212 * @returns true if a page is displayed, false otherwise
\r
214 public boolean isPageLoaded() {
\r
218 /** The simple name of the currently displayed page
\r
219 * @returns the simple page name (filename.extension)
\r
221 public String getCurrentPage() {
\r
222 return currentPage;
\r
225 /** Reloads the current page
\r
227 * This is quite a clever method, in that if a change of Locale has occurred since the
\r
228 * last setPage() or reloadPage(), the reloaded page will be looked for in the new
\r
231 public boolean reloadPage() {
\r
232 ComboBoxModel model = lstHistory.getModel();
\r
233 return setPage((HelpIconTitledURLItem)model.getSelectedItem());
\r
237 * Called when a hypertext link is updated.
\r
239 * @param e the event responsible for the update
\r
241 public void hyperlinkUpdate(HyperlinkEvent e) {
\r
242 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
\r
243 JEditorPane pane = (JEditorPane) e.getSource();
\r
244 if (e instanceof HTMLFrameHyperlinkEvent) {
\r
245 HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent)e;
\r
246 HTMLDocument doc = (HTMLDocument)pane.getDocument();
\r
247 doc.processHTMLFrameHyperlinkEvent(evt);
\r
250 setPage(e.getURL());
\r
251 } catch (Throwable t) {
\r
252 t.printStackTrace();
\r
258 javax.swing.text.html.HTMLEditorKit kit = null;
\r
260 public void createContents(URL htmlContents) throws IOException {
\r
261 InputStream in = getStream(htmlContents);
\r
263 kit = new HTMLEditorKit();
\r
267 public void createIndex(URL htmlIndex) {
\r
270 protected void buildTree(JTree tree, HTMLDocument htmlDoc, HTML.Tag tag, String id) {
\r
273 protected InputStream getStream(URL page) throws IOException {
\r
274 URLConnection conn = page.openConnection();
\r
275 if (conn instanceof HttpURLConnection) {
\r
276 HttpURLConnection hconn = (HttpURLConnection) conn;
\r
277 hconn.setInstanceFollowRedirects(false);
\r
278 int response = hconn.getResponseCode();
\r
280 InputStream in = conn.getInputStream();
\r
285 * Change the (HTML) document displayed in the help window
\r
286 * The complete URL will be built from:
\r
287 * (the previously provided) baseURL + "help/" + language + "/" + country + "/" + page
\r
288 * This mechanism allows locale-specific pages to be provided and used transparently.
\r
289 * When a page in the language of the current Locale is not available, the same page
\r
290 * for the default Locale will be looked for instead.
\r
292 * Help files are use the following directory structure:
\r
294 * <helpBase> = baseURL + "/help/"
\r
295 * <currentLocale> = <helpBase> + <ISO-639 code> + <ISO-3166 code>
\r
299 * myapp/help/ (helpBase)
\r
300 * myapp/help/images/ (optional location for common image files)
\r
301 * myapp/help/en/ (English)
\r
302 * myapp/help/en/US/ (English USA)
\r
303 * myapp/help/fr/ (French)
\r
304 * myapp/help/fr/CA (French Canadian}
\r
306 * Common supporting image and other files can be placed in the helpBase directory and
\r
307 * it's sub-directories. CSS stylesheets can be organised such that global styles are
\r
308 * stored in helpBase, and language-specific styles in the individual Locale directories.
\r
310 * @param page simple page name (no path)
\r
312 public boolean setPage(String page) {
\r
313 URL url = setPageImpl(page);
\r
314 boolean result = url != null ? true : false;
\r
316 if(result == true) { // loading has begun
\r
317 HTMLDocument docType = (HTMLDocument)helpDoc.getStyledDocument();
\r
318 Thread getDoc = new waitForDocTitle(page, url, true);
\r
319 getDoc.run(); // wait for it to complete then add the title to the history list
\r
325 public boolean setPage(HelpIconTitledURLItem item) {
\r
326 URL url = setPageImpl(item.getFilename());
\r
327 return url != null ? true : false;
\r
330 public boolean setPage(URL url) {
\r
331 boolean result = false;
\r
332 String base = helpBase.toString();
\r
333 String next = url.toString();
\r
335 if(next.startsWith(base)) { // page is within local help service
\r
336 int pagePos = next.lastIndexOf('/');
\r
337 String page = next.substring(pagePos+1);
\r
338 result = setPage(page);
\r
340 else { // external page, use full URL
\r
341 System.out.println("External URLs not permitted just now");
\r
346 protected URL setPageImpl(String page) {
\r
347 boolean result = false;
\r
350 if(helpBase != null && page != null) {
\r
352 u = new URL(helpBase, language + "/" + country + "/" + page); // country-sensitive help
\r
353 helpDoc.setPage(u); // load the page (asynchronously)
\r
355 } catch(IOException e) { // eeek! Country-specific page not available
\r
356 System.err.println("Page Not Found loading " + page + " for " + language + "_" + country);
\r
358 u = new URL(helpBase, language + "/" + page); // language-sensitive help
\r
359 helpDoc.setPage(u); // load the page (asynchronously)
\r
361 System.err.println("Page Found loading " + page + " for " + language);
\r
362 } catch(IOException f) { // eeek! Language-specific page not available
\r
363 System.err.println("Page Not Found loading " + page + " for " + language);
\r
364 try { // maybe the default language page is?
\r
365 u = new URL(helpBase, defaultLanguage + "/" + page); // locale-insensitive help
\r
366 helpDoc.setPage(u); // load the page (asynchronously)
\r
368 System.err.println("Page Found loading " + page + " for " + defaultLanguage);
\r
369 } catch(IOException g) { // nope! Page Not Found
\r
370 System.err.println("Page Not Found loading " + page);
\r
375 if(result == true) { // loading has begun
\r
376 pageLoaded = true; // not strictly true, but the URL was found to be valid
\r
377 currentPage = page;
\r
386 * Due to the HTML document being loaded asynchronously into the JTextPane helpDoc, the title tag
\r
387 * of the HTML document will not be available immediately for adding to the History list.
\r
389 * Therefore this monitor class is started in a new Thread. It waits for a TitleProperty to be
\r
390 * available from the JTextPane.styledDocument HTMLDocument.
\r
392 class waitForDocTitle extends Thread {
\r
397 /** Create the monitor
\r
398 * @param page The simple page name (not locale-specific)
\r
399 * @param url The page's URL (locale-specific)
\r
400 * @param local true if the page is part of the help set, false if it's external
\r
402 waitForDocTitle(String page, URL url, boolean local) {
\r
405 this.local = local;
\r
409 * Wait until the TitleProperty of the document has been parsed and added to the StyledDocument's
\r
412 public void run() {
\r
415 HTMLDocument html = (HTMLDocument)helpDoc.getStyledDocument();
\r
416 javax.swing.text.Element obj = null;
\r
417 while((docTitle = (String)html.getProperty(Document.TitleProperty)) == null && (obj = html.getElement("title")) == null) {
\r
418 System.out.println("Waiting");
\r
421 } catch(InterruptedException e) {}
\r
422 count++; // count how many times the loop has cycled
\r
423 if(count > 10) break; // don't get stuck in a race condition
\r
426 // at this point docTitle will be null or contain the HTML <title> element contents
\r
427 // there might also be an element with id="title"
\r
428 if(obj != null) { // if so, it is preferred to the <title> element itself
\r
429 obj = obj.getElement(0); // get it's first child - it had better be plain text else we're scuppered!
\r
431 docTitle = obj.getDocument().getText(obj.getStartOffset(),obj.getEndOffset() - obj.getStartOffset());
\r
432 } catch(Exception e) {
\r
433 System.err.println("Unable to find text contents of HTML Element with id=title");
\r
437 // check the title isn't already in the History by counting out all the unequal titles
\r
438 int stop = count = lstHistory.getItemCount();
\r
440 for(int i = 0; i < stop; i++) { // compare each one
\r
441 t = ((HelpIconTitledURLItem)lstHistory.getItemAt(i)).getTitle(); // the title from the ComboBox
\r
442 if(!t.equals(docTitle)) // not a match
\r
443 --count; // one down
\r
444 else // found the same title, so select it
\r
445 lstHistory.setSelectedIndex(i); // show the current doc in the combobox
\r
448 if(count == 0) { // found a unique title, so add it to the URL History
\r
449 HelpIconTitledURLItem item = new HelpIconTitledURLItem(docTitle, url, local);
\r
450 lstHistory.addItem(item);
\r
451 lstHistory.setSelectedItem(item); // select it (it's the latest)
\r
456 /** Help Contents tab */
\r
457 public static final int TAB_CONTENTS = 1;
\r
459 /** Help Index tab */
\r
460 public static final int TAB_INDEX = 2;
\r
462 /** Help Search tab */
\r
463 public static final int TAB_SEARCH = 3;
\r
465 /** Set the active navigator tab
\r
466 * @param tabSelect The tab to receive focus
\r
468 public void setNavigationTab(int tabSelect) {
\r
469 if(tabSelect >= 1 && tabSelect <= helpNavigator.getTabCount())
\r
470 helpNavigator.setSelectedIndex(tabSelect-1); // offset by -1 because zero indicates not to change it
\r
473 public void setNavigationContentsTreeRoot(TreeModel contentsModel) {
\r
474 contentsTree.setModel(contentsModel);
\r
477 public void setNavigationIndexTreeRoot(TreeModel indexModel) {
\r
478 indexTree.setModel(indexModel);
\r
482 public void setLocation(Point p, Component source) {
\r
484 if(!manualPosition) // only relocate if User hasn't previously positioned the window
\r
485 super.setLocation(p);
\r
488 public void setSize(Dimension d, Component source) {
\r
490 if(!manualPosition) // only resize if User hasn't previously positioned the window
\r
494 public void setDocking(boolean dock) {
\r
496 manualPosition = false;
\r
499 public boolean isDocking() {
\r
503 /** This method is called from within the constructor to
\r
504 * initialize the form.
\r
505 * WARNING: Do NOT modify this code. The content of this method is
\r
506 * always regenerated by the Form Editor.
\r
508 private void initComponents() {//GEN-BEGIN:initComponents
\r
509 helpToolbar = new javax.swing.JToolBar();
\r
510 btnBack = new javax.swing.JButton();
\r
511 btnForward = new javax.swing.JButton();
\r
512 btnRefresh = new javax.swing.JButton();
\r
513 btnOnline = new javax.swing.JToggleButton();
\r
514 lstHistory = new javax.swing.JComboBox();
\r
515 helpSplitter = new javax.swing.JSplitPane();
\r
516 helpNavigator = new javax.swing.JTabbedPane();
\r
517 contentsScroller = new javax.swing.JScrollPane();
\r
518 contentsTree = new javax.swing.JTree();
\r
519 indexPanel = new javax.swing.JPanel();
\r
520 indexSearchText = new javax.swing.JTextField();
\r
521 indexTree = new javax.swing.JTree();
\r
522 searchPanel = new javax.swing.JPanel();
\r
523 searchCriteriaText = new javax.swing.JTextField();
\r
524 searchResultsList = new javax.swing.JList();
\r
525 helpDocScroller = new javax.swing.JScrollPane();
\r
526 helpDoc = new javax.swing.JTextPane();
\r
529 setIconImage(icHelp.getImage());
\r
530 addComponentListener(new java.awt.event.ComponentAdapter() {
\r
531 public void componentMoved(java.awt.event.ComponentEvent evt) {
\r
532 formComponentMoved(evt);
\r
536 btnBack.setText("Back");
\r
537 btnBack.addActionListener(new java.awt.event.ActionListener() {
\r
538 public void actionPerformed(java.awt.event.ActionEvent evt) {
\r
539 btnBackActionPerformed(evt);
\r
543 helpToolbar.add(btnBack);
\r
545 btnForward.setText("Forward");
\r
546 btnForward.addActionListener(new java.awt.event.ActionListener() {
\r
547 public void actionPerformed(java.awt.event.ActionEvent evt) {
\r
548 btnForwardActionPerformed(evt);
\r
552 helpToolbar.add(btnForward);
\r
554 btnRefresh.setText("Refresh");
\r
555 btnRefresh.addActionListener(new java.awt.event.ActionListener() {
\r
556 public void actionPerformed(java.awt.event.ActionEvent evt) {
\r
557 btnRefreshActionPerformed(evt);
\r
561 helpToolbar.add(btnRefresh);
\r
563 btnOnline.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/tjworld/components/media/vistaOnline.gif")));
\r
564 helpToolbar.add(btnOnline);
\r
566 lstHistory.addActionListener(new java.awt.event.ActionListener() {
\r
567 public void actionPerformed(java.awt.event.ActionEvent evt) {
\r
568 lstHistoryActionPerformed(evt);
\r
572 helpToolbar.add(lstHistory);
\r
574 getContentPane().add(helpToolbar, java.awt.BorderLayout.SOUTH);
\r
576 helpSplitter.setDividerLocation(128);
\r
577 helpSplitter.setOneTouchExpandable(true);
\r
578 helpNavigator.setTabLayoutPolicy(javax.swing.JTabbedPane.SCROLL_TAB_LAYOUT);
\r
579 contentsTree.setBorder(new javax.swing.border.EtchedBorder());
\r
580 contentsTree.setName("Contents");
\r
581 contentsTree.setRootVisible(false);
\r
582 contentsTree.setShowsRootHandles(true);
\r
583 contentsScroller.setViewportView(contentsTree);
\r
585 helpNavigator.addTab("", new javax.swing.ImageIcon(getClass().getResource("/org/tjworld/components/media/help.gif")), contentsScroller);
\r
587 indexPanel.setLayout(new java.awt.BorderLayout());
\r
589 indexPanel.add(indexSearchText, java.awt.BorderLayout.NORTH);
\r
591 indexTree.setBorder(new javax.swing.border.EtchedBorder());
\r
592 indexTree.setRootVisible(false);
\r
593 indexTree.setShowsRootHandles(true);
\r
594 indexPanel.add(indexTree, java.awt.BorderLayout.CENTER);
\r
596 helpNavigator.addTab("", new javax.swing.ImageIcon(getClass().getResource("/org/tjworld/components/media/index.gif")), indexPanel);
\r
598 searchPanel.setLayout(new java.awt.BorderLayout());
\r
600 searchPanel.add(searchCriteriaText, java.awt.BorderLayout.NORTH);
\r
602 searchResultsList.setBorder(new javax.swing.border.EtchedBorder());
\r
603 searchPanel.add(searchResultsList, java.awt.BorderLayout.CENTER);
\r
605 helpNavigator.addTab("", new javax.swing.ImageIcon(getClass().getResource("/org/tjworld/components/media/helpsearch.gif")), searchPanel);
\r
607 helpSplitter.setLeftComponent(helpNavigator);
\r
609 helpDoc.setBorder(null);
\r
610 helpDoc.setEditable(false);
\r
611 helpDocScroller.setViewportView(helpDoc);
\r
613 helpSplitter.setRightComponent(helpDocScroller);
\r
615 getContentPane().add(helpSplitter, java.awt.BorderLayout.CENTER);
\r
618 }//GEN-END:initComponents
\r
620 private void btnRefreshActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRefreshActionPerformed
\r
622 }//GEN-LAST:event_btnRefreshActionPerformed
\r
624 private void btnForwardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnForwardActionPerformed
\r
625 int next = lstHistory.getSelectedIndex()+1;
\r
626 if(next < lstHistory.getItemCount()) {
\r
627 HelpIconTitledURLItem item = (HelpIconTitledURLItem)lstHistory.getItemAt(next);
\r
628 if(currentPage != item.getFilename()) { // don't react if the current page was selected
\r
629 lstHistory.setSelectedIndex(next);
\r
633 }//GEN-LAST:event_btnForwardActionPerformed
\r
635 private void btnBackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBackActionPerformed
\r
636 int last = lstHistory.getSelectedIndex()-1;
\r
638 HelpIconTitledURLItem item = (HelpIconTitledURLItem)lstHistory.getItemAt(last);
\r
639 if(currentPage != item.getFilename()) { // don't react if the current page was selected
\r
640 lstHistory.setSelectedIndex(last);
\r
644 }//GEN-LAST:event_btnBackActionPerformed
\r
646 private void formComponentMoved(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_formComponentMoved
\r
648 if(!inExtMove) manualPosition = true;
\r
651 }//GEN-LAST:event_formComponentMoved
\r
653 private void lstHistoryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_lstHistoryActionPerformed
\r
654 HelpIconTitledURLItem item = (HelpIconTitledURLItem)lstHistory.getSelectedItem();
\r
655 if(currentPage != item.getFilename()) // don't react if the current page was selected
\r
657 }//GEN-LAST:event_lstHistoryActionPerformed
\r
659 /** Tree Selection Listener for Content and Index trees.
\r
660 * Doesn't matter whether the source is the Content or Index tree
\r
662 public void valueChanged(TreeSelectionEvent e) {
\r
663 DefaultMutableTreeNode node = (DefaultMutableTreeNode)((JTree)e.getSource()).getLastSelectedPathComponent();
\r
664 if (node != null) {
\r
665 Object nodeInfo = node.getUserObject();
\r
666 if (node.isLeaf() && (nodeInfo instanceof HelpIconTitledURLItem))
\r
667 setPage((HelpIconTitledURLItem)nodeInfo);
\r
671 /** Choose the Java Look & Feel
\r
672 * @param lf The L&F name
\r
674 public void setLookAndFeel(String lf) {
\r
675 Cursor curCursor = getCursor(); // save the existing cursor
\r
676 setCursor(new Cursor(Cursor.WAIT_CURSOR)); // let the user know this might take a while
\r
679 UIManager.setLookAndFeel(lf);
\r
681 // now adjust the frame decoration depending on whether the L&F supports painting it
\r
682 setVisible(false); // hide the frame while the decoration is changed
\r
683 dispose(); // detatch all of the native windowing resources
\r
685 if(UIManager.getLookAndFeel().getSupportsWindowDecorations()) {
\r
686 setUndecorated(true); // don't use the Host window decoration
\r
687 getRootPane().setWindowDecorationStyle(javax.swing.JRootPane.FRAME);
\r
689 setUndecorated(false); // L&F doesn't support decorating the frame
\r
690 getRootPane().setWindowDecorationStyle(javax.swing.JRootPane.NONE);
\r
692 } catch(UnsupportedLookAndFeelException e) { // uh-oh, a problem
\r
694 System.err.println("Couldn't switch to " + lf + ", selecting Cross Platform instead");
\r
695 UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); // try to recover gracefully
\r
696 } catch(Exception g) { // major problem!
\r
697 System.err.println("Couldn't return to Cross Platform L&F - eeek!");
\r
698 g.printStackTrace();
\r
700 } catch(Exception f) { // oh pooey, what do I do now?
\r
701 System.err.println("Couldn't load " + lf);
\r
702 f.printStackTrace();
\r
703 } finally { // do this in any case
\r
704 SwingUtilities.updateComponentTreeUI(this); // update the view
\r
706 /* one problem is that the JTextPane has long lines of HTML paragraph text which pack()
\r
707 * allows to extend very wide! So here I take a note of the existing width of the JTextPane
\r
708 * and explictly set it after pack()
\r
710 Dimension dim = getSize();
\r
711 pack(); // make sure to adjust for potentially altered component sizes
\r
716 setCursor(curCursor); // restore the cursor
\r
719 /** Exit the Application
\r
720 * @param args the command line arguments
\r
722 public static void main(String args[]) {
\r
723 new xhtmlHelp().show();
\r
726 // Variables declaration - do not modify//GEN-BEGIN:variables
\r
727 private javax.swing.JToolBar helpToolbar;
\r
728 private javax.swing.JButton btnBack;
\r
729 private javax.swing.JButton btnForward;
\r
730 private javax.swing.JButton btnRefresh;
\r
731 private javax.swing.JToggleButton btnOnline;
\r
732 private javax.swing.JComboBox lstHistory;
\r
733 private javax.swing.JSplitPane helpSplitter;
\r
734 private javax.swing.JTabbedPane helpNavigator;
\r
735 private javax.swing.JScrollPane contentsScroller;
\r
736 private javax.swing.JTree contentsTree;
\r
737 private javax.swing.JPanel indexPanel;
\r
738 private javax.swing.JTextField indexSearchText;
\r
739 private javax.swing.JTree indexTree;
\r
740 private javax.swing.JPanel searchPanel;
\r
741 private javax.swing.JTextField searchCriteriaText;
\r
742 private javax.swing.JList searchResultsList;
\r
743 private javax.swing.JScrollPane helpDocScroller;
\r
744 private javax.swing.JTextPane helpDoc;
\r
745 // End of variables declaration//GEN-END:variables
\r