001: package net.sourceforge.squirrel_sql.client.gui;
002:
003: /*
004: * Copyright (C) 2003 Colin Bell
005: * colbell@users.sourceforge.net
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: import java.awt.BorderLayout;
022: import java.awt.Point;
023: import java.awt.event.MouseAdapter;
024: import java.awt.event.MouseEvent;
025: import java.io.IOException;
026: import java.net.URL;
027: import java.util.LinkedList;
028: import java.util.List;
029: import java.util.ListIterator;
030:
031: import javax.swing.BorderFactory;
032: import javax.swing.JEditorPane;
033: import javax.swing.JPanel;
034: import javax.swing.JScrollPane;
035: import javax.swing.event.EventListenerList;
036: import javax.swing.event.HyperlinkEvent;
037: import javax.swing.event.HyperlinkListener;
038: import javax.swing.text.html.HTMLDocument;
039: import javax.swing.text.html.HTMLFrameHyperlinkEvent;
040:
041: import net.sourceforge.squirrel_sql.fw.gui.CursorChanger;
042: import net.sourceforge.squirrel_sql.fw.gui.TextPopupMenu;
043: import net.sourceforge.squirrel_sql.fw.util.StringManager;
044: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
045: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
046: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
047:
048: /**
049: * This panel shows the contents of a HTML file.
050: *
051: * @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
052: */
053: public class HtmlViewerPanel extends JPanel {
054: /** Logger for this class. */
055: private final static ILogger s_log = LoggerController
056: .createLogger(HtmlViewerPanel.class);
057:
058: /** Internationalized strings for this class. */
059: private static final StringManager s_stringMgr = StringManagerFactory
060: .getStringManager(HtmlViewerPanel.class);
061:
062: /** Text area containing the HTML. */
063: private final JEditorPane _contentsTxt = new JEditorPane();
064:
065: /** <TT>JScrollPane</TT> for <TT>_contentsText</TT>. */
066: private JScrollPane _contentsScrollPane;
067:
068: /** Original URL (home). */
069: private URL _homeURL;
070:
071: /** Current URL. */
072: private URL _currentURL;
073:
074: /** History of links. */
075: private final List<URL> _history = new LinkedList<URL>();
076:
077: /** Current index into <TT>_history</TT>. */
078: private int _historyIndex = -1;
079:
080: /**
081: * Collection of listeners for events in this object.
082: */
083: private EventListenerList _listenerList = new EventListenerList();
084:
085: /**
086: * Ctor.
087: *
088: * @param url URL to home document.
089: */
090: public HtmlViewerPanel(URL url) {
091: super ();
092: createGUI();
093: setHomeURL(url);
094: setURL(url);
095: }
096:
097: /**
098: * Retrieve the current URL.
099: *
100: * @return The current URL.
101: */
102: public URL getURL() {
103: return _currentURL;
104: }
105:
106: /**
107: * Retrieve the home URL.
108: *
109: * @return The home URL.
110: */
111: public URL getHomeURL() {
112: return _homeURL;
113: }
114:
115: /**
116: * Specify the URL that is to the consider the "Home" URL. THis
117: * does <EM>not</EM> change the current URL for this viewer.
118: *
119: * @param homeURL The new home URL.
120: */
121: public void setHomeURL(URL homeURL) {
122: _homeURL = homeURL;
123: fireHomeURLChanged();
124: }
125:
126: /**
127: * Adds a listener to this object.
128: *
129: * @param lis Listener to be added.
130: */
131: public void addListener(IHtmlViewerPanelListener lis) {
132: _listenerList.add(IHtmlViewerPanelListener.class, lis);
133: }
134:
135: /**
136: * Removes a listener from this object.
137: *
138: * @param lis Listener to be removed.
139: */
140: void removeListener(IHtmlViewerPanelListener lis) {
141: _listenerList.remove(IHtmlViewerPanelListener.class, lis);
142: }
143:
144: public synchronized void gotoURL(URL url) throws IOException {
145: if (url == null) {
146: throw new IllegalArgumentException("URL == null");
147: }
148: if (!url.equals(_currentURL)) {
149: ListIterator<URL> it = _history
150: .listIterator(_historyIndex + 1);
151: while (it.hasNext()) {
152: it.next();
153: it.remove();
154: }
155: _history.add(url);
156: _historyIndex = _history.size() - 1;
157: _contentsTxt.setPage(url);
158: _currentURL = url;
159: fireURLChanged();
160: }
161: }
162:
163: public synchronized void goBack() {
164: if (_historyIndex > 0 && _historyIndex < _history.size()) {
165: displayURL(_history.get(--_historyIndex));
166: }
167: }
168:
169: public synchronized void goForward() {
170: if (_historyIndex > -1 && _historyIndex < _history.size() - 1) {
171: displayURL(_history.get(++_historyIndex));
172: }
173: }
174:
175: public synchronized void goHome() {
176: _historyIndex = 0;
177: displayURL(_homeURL);
178: }
179:
180: public void refreshPage() {
181: final Point pos = _contentsScrollPane.getViewport()
182: .getViewPosition();
183: displayURL(_currentURL);
184: _contentsScrollPane.getViewport().setViewPosition(pos);
185: }
186:
187: /**
188: * Displayed the passed URL in this panel.
189: *
190: * @param url URL to be displayed.
191: */
192: private synchronized void setURL(URL url) {
193: if (url != null) {
194: CursorChanger cursorChg = new CursorChanger(this );
195: cursorChg.show();
196: try {
197: // Causes NPE in JDK 1.3.1
198: //_contentsTxt.setText("");
199: displayURL(url);
200: _history.add(url);
201: _historyIndex = 0;
202: } finally {
203: cursorChg.restore();
204: }
205: }
206: }
207:
208: /**
209: * Display the passed URL. This method does not affect the URL history, it
210: * merely displays the URL.
211: *
212: * @param url The URL to display.
213: */
214: private void displayURL(URL url) {
215: if (url != null) {
216: try {
217: _contentsTxt.setPage(url);
218: _currentURL = url;
219: fireURLChanged();
220: } catch (Exception ex) {
221: // i18n[HtmlViewerPanel.error.displayurl=Error displaying URL]
222: s_log.error(s_stringMgr
223: .getString("HtmlViewerPanel.error.displayurl"),
224: ex);
225: }
226: }
227: }
228:
229: /**
230: * Fire a "URL changed" event to all listeners.
231: */
232: private void fireURLChanged() {
233: // Guaranteed to be non-null.
234: Object[] listeners = _listenerList.getListenerList();
235: // Process the listeners last to first, notifying
236: // those that are interested in this event.
237: HtmlViewerPanelListenerEvent evt = null;
238: for (int i = listeners.length - 2; i >= 0; i -= 2) {
239: if (listeners[i] == IHtmlViewerPanelListener.class) {
240: // Lazily create the event.
241: if (evt == null) {
242: evt = new HtmlViewerPanelListenerEvent(this );
243: }
244: ((IHtmlViewerPanelListener) listeners[i + 1])
245: .currentURLHasChanged(evt);
246: }
247: }
248: }
249:
250: /**
251: * Fire a "Home URL changed" event to all listeners.
252: */
253: private void fireHomeURLChanged() {
254: // Guaranteed to be non-null.
255: Object[] listeners = _listenerList.getListenerList();
256: // Process the listeners last to first, notifying
257: // those that are interested in this event.
258: HtmlViewerPanelListenerEvent evt = null;
259: for (int i = listeners.length - 2; i >= 0; i -= 2) {
260: if (listeners[i] == IHtmlViewerPanelListener.class) {
261: // Lazily create the event.
262: if (evt == null) {
263: evt = new HtmlViewerPanelListenerEvent(this );
264: }
265: ((IHtmlViewerPanelListener) listeners[i + 1])
266: .homeURLHasChanged(evt);
267: }
268: }
269: }
270:
271: /**
272: * Create user interface.
273: */
274: private void createGUI() {
275: setLayout(new BorderLayout());
276: add(createMainPanel(), BorderLayout.CENTER);
277: }
278:
279: /**
280: * Create the main panel.
281: */
282: private JPanel createMainPanel() {
283: _contentsTxt.setEditable(false);
284: _contentsTxt.setContentType("text/html");
285: final TextPopupMenu pop = new TextPopupMenu();
286: pop.setTextComponent(_contentsTxt);
287: _contentsTxt.addMouseListener(new MouseAdapter() {
288: public void mousePressed(MouseEvent evt) {
289: if (evt.isPopupTrigger()) {
290: pop
291: .show(evt.getComponent(), evt.getX(), evt
292: .getY());
293: }
294: }
295:
296: public void mouseReleased(MouseEvent evt) {
297: if (evt.isPopupTrigger()) {
298: pop
299: .show(evt.getComponent(), evt.getX(), evt
300: .getY());
301: }
302: }
303: });
304:
305: final JPanel pnl = new JPanel(new BorderLayout());
306: _contentsTxt.setBorder(BorderFactory.createEmptyBorder(0, 1, 0,
307: 0));
308: _contentsTxt.addHyperlinkListener(createHyperLinkListener());
309: _contentsScrollPane = new JScrollPane(_contentsTxt,
310: JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
311: JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
312: pnl.add(_contentsScrollPane, BorderLayout.CENTER);
313:
314: return pnl;
315: }
316:
317: private HyperlinkListener createHyperLinkListener() {
318: return new HyperlinkListener() {
319: public void hyperlinkUpdate(HyperlinkEvent e) {
320: if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
321: if (e instanceof HTMLFrameHyperlinkEvent) {
322: ((HTMLDocument) _contentsTxt.getDocument())
323: .processHTMLFrameHyperlinkEvent((HTMLFrameHyperlinkEvent) e);
324: } else {
325: try {
326: gotoURL(e.getURL());
327: } catch (IOException ex) {
328: // i18n[HtmlViewerPanel.error.processhyperlink=Error processing hyperlink]
329: s_log
330: .error(
331: s_stringMgr
332: .getString("HtmlViewerPanel.error.processhyperlink"),
333: ex);
334: }
335: }
336: }
337: }
338: };
339: }
340: }
|