KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > finalist > jaggenerator > HtmlContentPopUp


1 /* Copyright (C) 2003 Finalist IT Group
2  *
3  * This file is part of JAG - the Java J2EE Application Generator
4  *
5  * JAG is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * JAG is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with JAG; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */

17
18 package com.finalist.jaggenerator;
19
20 import com.finalist.jaggenerator.JagGenerator;
21
22 import javax.swing.text.html.HTMLDocument JavaDoc;
23 import javax.swing.*;
24 import javax.swing.event.HyperlinkListener JavaDoc;
25 import javax.swing.event.HyperlinkEvent JavaDoc;
26 import javax.swing.event.DocumentListener JavaDoc;
27 import javax.swing.event.DocumentEvent JavaDoc;
28 import java.net.URL JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.awt.*;
31 import java.awt.event.KeyEvent JavaDoc;
32 import java.util.*;
33
34 /**
35  * A general purpose popup window for displaying hyperlinked HTML pages. The window may be initialised
36  * with either a URL or with a String containing HTML (but a HtmlContentPopUp initialised with a String does
37  * not support hyperlinks).
38  * <p>
39  * The HtmlContentPopup allows hyperlinks to be followed and maintains a page history, which is navigatable
40  * with a back and forward button. The back and forward buttons also may be triggered by the familiar
41  * keyboard shortcuts (Backspace or ALT-left_arrow for 'back', and ALT+right_arrow for 'forward'), and
42  * the popup may be dismissed with the ESCAPE key.
43  * <p>
44  * The page history maintained by this component includes scrollbar position information. For example if you
45  * hyperlink to document#2 from the <b>end</b> of document#1, and then navigate back to document#1: you will
46  * find yourself back at the very same place in document#1 where you left it (the end, in this case).
47  * <p>
48  * Any hyperlinked URLs that end in <code>!!!EXTERNAL!!!</code> (<code>HtmlContentPopup.EXTERNAL_TAG</code>)
49  * will attempt to launch the link in an external browser - this is defaulted to Internet Explorer (sorry!).
50  *
51  * @author Michael O'Connor - Finalist IT Group
52  */

53 public class HtmlContentPopUp extends javax.swing.JDialog JavaDoc {
54    /** A return status code - returned if Cancel button has been pressed */
55    public static final int RET_CANCEL = 0;
56    /** A return status code - returned if OK button has been pressed */
57    public static final int RET_OK = 1;
58    private String JavaDoc externalBrowserCommand = "\"C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE\" ";
59    private final ArrayList pageHistory = new ArrayList();
60    private int historyPos = 0;
61    private String JavaDoc initialContent;
62    private static final String JavaDoc EXTERNAL_TAG = "!!!EXTERNAL!!!";
63    private static final int WIDTH = 600;
64    private static final int HEIGHT = 700;
65
66
67    /**
68     * Creates new form HtmlAboutPopUp with the specified content.
69     *
70     * @param parent the parent frame.
71     * @param title the title for the popup.
72     * @param modal whether or not the popup is modal.
73     * @param html the HTML content for the popup.
74     * @param navigation set to <code>true</code> if 'back' and 'forward' navigation buttons are required.
75     */

76    public HtmlContentPopUp(java.awt.Frame JavaDoc parent, String JavaDoc title, boolean modal, String JavaDoc html, boolean navigation) {
77       this(parent, title, modal, html, null, navigation);
78    }
79
80    /**
81     * Creates new form HtmlAboutPopUp with the specified content.
82     *
83     * @param parent the parent frame.
84     * @param title the title for the popup.
85     * @param modal whether or not the popup is modal.
86     * @param html the HTML content for the popup.
87     */

88    public HtmlContentPopUp(java.awt.Frame JavaDoc parent, String JavaDoc title, boolean modal, String JavaDoc html) {
89       this(parent, title, modal, html, null, true);
90    }
91
92    /**
93     * Creates new form HtmlAboutPopUp with a specified URL.
94     *
95     * @param parent the parent frame.
96     * @param title the title for the popup.
97     * @param modal whether or not the popup is modal.
98     * @param url the URL of the HTML content.
99     */

100    public HtmlContentPopUp(java.awt.Frame JavaDoc parent, String JavaDoc title, boolean modal, URL JavaDoc url) {
101       this(parent, title, modal, null, url, true);
102    }
103
104    private HtmlContentPopUp(java.awt.Frame JavaDoc parent, String JavaDoc title, boolean modal,
105                             String JavaDoc html, URL JavaDoc url, boolean navigation) {
106       super(parent, modal);
107       this.initialContent = html;
108       initComponents();
109       if (!navigation) {
110          buttonPanel.remove(navigationPanel);
111          //navigationPanel.setVisible(false);
112
}
113
114       jTextPane1.addHyperlinkListener(new HyperlinkListener JavaDoc() {
115          public void hyperlinkUpdate(HyperlinkEvent JavaDoc e) {
116             if (initialContent == null && e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
117                try {
118                   URL JavaDoc link = e.getURL();
119                   int externalTagPos = link.toString().indexOf(EXTERNAL_TAG);
120                   if (externalTagPos != -1) {
121                      String JavaDoc realLink = link.toString().substring(0, externalTagPos);
122                      JagGenerator.logToConsole("Launching external browser for " + realLink);
123                      Runtime.getRuntime().exec(externalBrowserCommand + realLink);
124                      return;
125                   }
126                   int size = pageHistory.size();
127                   if (historyPos == size) {
128                      pageHistory.add(new Bookmark());
129                   } else {
130                      updateCurrentBookmark();
131                      for (int i = size - 1; i > historyPos; i--) {
132                         pageHistory.remove(i);
133                      }
134                   }
135                   jTextPane1.setPage(link);
136                   historyPos++;
137                   forwardButton.setEnabled(false);
138                   backButton.setEnabled(true);
139                } catch (IOException JavaDoc e1) {
140                   //dead link - do nothing.
141
}
142             }
143          }
144       });
145
146       setSize(WIDTH, HEIGHT);
147       Dimension screenSize = (parent == null) ?
148             new JFrame().getToolkit().getScreenSize() : parent.getToolkit().getScreenSize();
149       this.setLocation(
150             (int) ((screenSize.getWidth() / 2) - (WIDTH / 2)),
151             (int) ((screenSize.getHeight() / 2) - (HEIGHT / 2)));
152
153       setTitle(title);
154       jTextPane1.setEditable(false);
155       if (html == null) {
156          try {
157             jTextPane1.setPage(url);
158             //pageHistory.add(new Bookmark());
159

160          } catch (IOException JavaDoc e) {
161             html = "Bad URL: " + url;
162             JagGenerator.logToConsole(html);
163             jTextPane1.setText(html);
164          }
165       } else {
166          jTextPane1.setContentType("text/html");
167          jTextPane1.setText(html);
168
169       }
170       jTextPane1.setCaretPosition(0);
171    }
172
173
174    /** @return the return status of this dialog - one of RET_OK or RET_CANCEL */
175    public int getReturnStatus() {
176       return returnStatus;
177    }
178
179    public String JavaDoc getExternalBrowserCommand() {
180       return externalBrowserCommand;
181    }
182
183    public void setExternalBrowserCommand(String JavaDoc externalBrowserCommand) {
184       this.externalBrowserCommand = externalBrowserCommand;
185    }
186
187    /** This method is called from within the constructor to
188     * initialize the form.
189     * WARNING: Do NOT modify this code. The content of this method is
190     * always regenerated by the Form Editor.
191     */

192    private void initComponents() {//GEN-BEGIN:initComponents
193
buttonPanel = new javax.swing.JPanel JavaDoc();
194       navigationPanel = new javax.swing.JPanel JavaDoc();
195       backButton = new javax.swing.JButton JavaDoc();
196       forwardButton = new javax.swing.JButton JavaDoc();
197       okButtonPanel = new javax.swing.JPanel JavaDoc();
198       okButton = new javax.swing.JButton JavaDoc();
199       jScrollPane1 = new javax.swing.JScrollPane JavaDoc();
200       jTextPane1 = new javax.swing.JTextPane JavaDoc();
201
202       setTitle("");
203       addWindowListener(new java.awt.event.WindowAdapter JavaDoc() {
204          public void windowClosing(java.awt.event.WindowEvent JavaDoc evt) {
205             closeDialog(evt);
206          }
207       });
208
209       buttonPanel.setLayout(new java.awt.BorderLayout JavaDoc());
210
211       backButton.setText("<<");
212       backButton.setToolTipText("back");
213       backButton.setEnabled(false);
214       backButton.addActionListener(new java.awt.event.ActionListener JavaDoc() {
215          public void actionPerformed(java.awt.event.ActionEvent JavaDoc evt) {
216             backButtonActionPerformed(evt);
217          }
218       });
219
220       navigationPanel.add(backButton);
221
222       forwardButton.setText(">>");
223       forwardButton.setToolTipText("forward");
224       forwardButton.setEnabled(false);
225       forwardButton.addActionListener(new java.awt.event.ActionListener JavaDoc() {
226          public void actionPerformed(java.awt.event.ActionEvent JavaDoc evt) {
227             forwardButtonActionPerformed(evt);
228          }
229       });
230
231       navigationPanel.add(forwardButton);
232
233       buttonPanel.add(navigationPanel, java.awt.BorderLayout.WEST);
234
235       okButton.setText("OK");
236       okButton.setSelected(true);
237       okButton.addActionListener(new java.awt.event.ActionListener JavaDoc() {
238          public void actionPerformed(java.awt.event.ActionEvent JavaDoc evt) {
239             okButtonActionPerformed(evt);
240          }
241       });
242
243       okButtonPanel.add(okButton);
244
245       buttonPanel.add(okButtonPanel, java.awt.BorderLayout.EAST);
246
247       getContentPane().add(buttonPanel, java.awt.BorderLayout.SOUTH);
248
249       jTextPane1.setDocument(new HTMLDocument JavaDoc());
250       jTextPane1.setEditable(false);
251       jTextPane1.setFont(new java.awt.Font JavaDoc("Serif", 1, 14));
252       jTextPane1.addKeyListener(new java.awt.event.KeyAdapter JavaDoc() {
253          public void keyPressed(java.awt.event.KeyEvent JavaDoc evt) {
254             shortcutKeyPressed(evt);
255          }
256       });
257
258       jScrollPane1.setViewportView(jTextPane1);
259
260       getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
261
262       pack();
263    }//GEN-END:initComponents
264

265    private void shortcutKeyPressed(java.awt.event.KeyEvent JavaDoc evt) {//GEN-FIRST:event_shortcutKeyPressed
266
if (backButton.isEnabled() &&
267             (evt.getKeyCode() == KeyEvent.VK_BACK_SPACE ||
268             (((evt.getModifiersEx() & KeyEvent.ALT_DOWN_MASK) == KeyEvent.ALT_DOWN_MASK) &&
269             evt.getKeyCode() == KeyEvent.VK_LEFT))) {
270          backButtonActionPerformed(null);
271       } else if (forwardButton.isEnabled() &&
272             (((evt.getModifiersEx() & KeyEvent.ALT_DOWN_MASK) == KeyEvent.ALT_DOWN_MASK) &&
273             evt.getKeyCode() == KeyEvent.VK_RIGHT)) {
274          forwardButtonActionPerformed(null);
275       } else if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
276          doClose(RET_CANCEL);
277       }
278
279    }//GEN-LAST:event_shortcutKeyPressed
280

281    private void forwardButtonActionPerformed(java.awt.event.ActionEvent JavaDoc evt) {//GEN-FIRST:event_forwardButtonActionPerformed
282
try {
283          updateCurrentBookmark();
284          Bookmark next = (Bookmark) pageHistory.get(++historyPos);
285          gotoBookmark(next);
286          forwardButton.setEnabled(historyPos != (pageHistory.size() - 1));
287          backButton.setEnabled(true);
288       } catch (IOException JavaDoc e1) {
289          //dead link - do nothing.
290
}
291    }//GEN-LAST:event_forwardButtonActionPerformed
292

293    private void backButtonActionPerformed(java.awt.event.ActionEvent JavaDoc evt) {//GEN-FIRST:event_backButtonActionPerformed
294
try {
295          if (historyPos != pageHistory.size()) {
296             updateCurrentBookmark();
297          } else {
298             pageHistory.add(new Bookmark());
299          }
300
301          Bookmark previous = (Bookmark) pageHistory.get(--historyPos);
302          gotoBookmark(previous);
303          forwardButton.setEnabled(true);
304          backButton.setEnabled(historyPos != 0);
305
306       } catch (IOException JavaDoc e1) {
307          //dead link - do nothing.
308
}
309    }//GEN-LAST:event_backButtonActionPerformed
310

311    private void gotoBookmark(final Bookmark next) throws IOException JavaDoc {
312       jTextPane1.setPage(next.url);
313       waitForSetPageDone(jTextPane1);
314       jScrollPane1.getViewport().setViewPosition(next.pos);
315       //jTextPane1.scrollRectToVisible(next.pos);
316

317    }
318
319    private void updateCurrentBookmark() {
320       pageHistory.remove(historyPos);
321       pageHistory.add(historyPos, new Bookmark());
322    }
323
324    private void waitForSetPageDone(final JTextPane pane) {
325       /* After JTextPane.setPage(url), you need to wait until page is
326        * fully loaded since setPage is asynchronous and returns
327        * immediately! */

328       synchronized (pane) {
329          pane.getDocument().addDocumentListener(new DocumentListener JavaDoc() {
330             public void insertUpdate(DocumentEvent JavaDoc e) {
331             }
332
333             public void removeUpdate(DocumentEvent JavaDoc e) {
334             }
335
336             public void changedUpdate(DocumentEvent JavaDoc evt) {
337                synchronized(pane) {
338                   pane.notify();
339                }
340             }
341          });
342          try {
343             pane.wait(1000);
344          } // release lock, wait for notify
345
// unblock after 1 sec in case hung
346
catch (InterruptedException JavaDoc ie) {
347             ie.printStackTrace();
348          }
349       }
350    }
351
352    private void okButtonActionPerformed(java.awt.event.ActionEvent JavaDoc evt) {//GEN-FIRST:event_okButtonActionPerformed
353
doClose(RET_OK);
354    }//GEN-LAST:event_okButtonActionPerformed
355

356    /** Closes the dialog */
357    private void closeDialog(java.awt.event.WindowEvent JavaDoc evt) {//GEN-FIRST:event_closeDialog
358
doClose(RET_CANCEL);
359    }//GEN-LAST:event_closeDialog
360

361    private void doClose(int retStatus) {
362       returnStatus = retStatus;
363       setVisible(false);
364       dispose();
365    }
366
367
368    // Variables declaration - do not modify//GEN-BEGIN:variables
369
private javax.swing.JButton JavaDoc backButton;
370    private javax.swing.JPanel JavaDoc buttonPanel;
371    private javax.swing.JButton JavaDoc forwardButton;
372    private javax.swing.JScrollPane JavaDoc jScrollPane1;
373    private javax.swing.JTextPane JavaDoc jTextPane1;
374    private javax.swing.JPanel JavaDoc navigationPanel;
375    private javax.swing.JButton JavaDoc okButton;
376    private javax.swing.JPanel JavaDoc okButtonPanel;
377    // End of variables declaration//GEN-END:variables
378

379    private int returnStatus = RET_CANCEL;
380
381
382    class Bookmark {
383       /**
384        * A Bookmark is a URL of a HTML page, along with a record of the viewport upper-left corner.
385        * This enables navigation to and from <i>a particular position</i> within a page.
386        */

387       public Bookmark() {
388          this.url = jTextPane1.getPage();
389          this.pos = jScrollPane1.getViewport().getViewPosition();
390       }
391
392       private URL JavaDoc url;
393       private Point pos;
394
395       public String JavaDoc toString() {
396          return pos + "@" + url.toString().substring(url.toString().lastIndexOf('/'));
397       }
398    }
399
400 }
401
402
403
Popular Tags