0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: package org.openide.awt;
0043:
0044: import java.awt.BorderLayout;
0045: import java.awt.Component;
0046: import java.awt.GridBagConstraints;
0047: import java.awt.GridBagLayout;
0048: import java.awt.Insets;
0049: import java.awt.event.ActionEvent;
0050: import java.awt.event.ActionListener;
0051: import java.beans.PropertyChangeEvent;
0052: import java.beans.PropertyChangeListener;
0053: import java.io.IOException;
0054: import java.net.MalformedURLException;
0055: import java.net.URL;
0056: import java.util.logging.Logger;
0057: import javax.accessibility.Accessible;
0058: import javax.accessibility.AccessibleContext;
0059: import javax.imageio.ImageIO;
0060: import javax.swing.Icon;
0061: import javax.swing.JButton;
0062: import javax.swing.JComboBox;
0063: import javax.swing.JComponent;
0064: import javax.swing.JFrame;
0065: import javax.swing.JLabel;
0066: import javax.swing.JPanel;
0067: import javax.swing.JScrollPane;
0068: import javax.swing.JToolBar;
0069: import javax.swing.ListModel;
0070: import javax.swing.SwingUtilities;
0071: import javax.swing.WindowConstants;
0072: import org.openide.util.Exceptions;
0073: import org.openide.util.Lookup;
0074: import org.openide.util.NbBundle;
0075: import org.openide.util.RequestProcessor;
0076:
0077: /**
0078: * Object that provides viewer for HTML pages.
0079: * <p>If all you want to do is to show some URL, this
0080: * is overkill. Just use {@link HtmlBrowser.URLDisplayer#showURL} instead. Using <code>HtmlBrowser</code>
0081: * is appropriate mainly if you want to embed a web browser in some other GUI component
0082: * (if the user has selected an external browser, this will fall back to a simple Swing
0083: * renderer). Similarly <code>Impl</code> (coming from a <code>Factory</code>) is the lower-level
0084: * renderer itself (sans toolbar).
0085: * <p>Summary: for client use, try <code>URLDisplayer.showURL</code>, or for more control
0086: * or where embedding is needed, create an <code>HtmlBrowser</code>. For provider use,
0087: * create a <code>Factory</code> and register an instance of it to lookup.
0088: */
0089: public class HtmlBrowser extends JPanel {
0090: // static ....................................................................
0091:
0092: /** generated Serialized Version UID */
0093: private static final long serialVersionUID = 2912844785502987960L;
0094:
0095: /** Preferred width of the browser */
0096: public static final int DEFAULT_WIDTH = 400;
0097:
0098: /** Preferred height of the browser */
0099: public static final int DEFAULT_HEIGHT = 600;
0100:
0101: /** current implementation of html browser */
0102: private static Factory browserFactory;
0103:
0104: /** home page URL */
0105: private static String homePage = null;
0106:
0107: /** Icons for buttons. */
0108: private Icon iBack;
0109: private Icon iForward;
0110: private Icon iHome;
0111: private Icon iReload;
0112: private Icon iStop;
0113: private Icon iHistory;
0114:
0115: // variables .................................................................
0116:
0117: /** currently used implementation of browser */
0118: final Impl browserImpl;
0119:
0120: /** true = do not listen on changes of URL on cbLocation */
0121: private boolean everythinkIListenInCheckBoxIsUnimportant = false;
0122:
0123: /** toolbar visible property */
0124: private boolean toolbarVisible = false;
0125:
0126: /** status line visible property */
0127: private boolean statusLineVisible = false;
0128:
0129: /** Listens on changes in HtmlBrowser.Impl and HtmlBrowser visual components.
0130: */
0131: private BrowserListener browserListener;
0132:
0133: // visual components .........................................................
0134: private JButton bBack;
0135:
0136: // visual components .........................................................
0137: private JButton bForward;
0138:
0139: // visual components .........................................................
0140: private JButton bHome;
0141:
0142: // visual components .........................................................
0143: private JButton bReload;
0144:
0145: // visual components .........................................................
0146: private JButton bStop;
0147:
0148: // visual components .........................................................
0149: private JButton bHistory;
0150:
0151: /** URL chooser */
0152: private JComboBox cbLocation;
0153: private JLabel cbLabel;
0154: private JLabel lStatusLine;
0155: final Component browserComponent;
0156: private JPanel head;
0157: private RequestProcessor rp = new RequestProcessor();
0158:
0159: // init ......................................................................
0160:
0161: /**
0162: * Creates new html browser with toolbar and status line.
0163: */
0164: public HtmlBrowser() {
0165: this (true, true);
0166: }
0167:
0168: /**
0169: * Creates new html browser.
0170: *
0171: * @param toolbar visibility of toolbar
0172: * @param statusLine visibility of statusLine
0173: */
0174: public HtmlBrowser(boolean toolbar, boolean statusLine) {
0175: this (null, toolbar, statusLine);
0176: }
0177:
0178: /**
0179: * Creates new html browser.
0180: *
0181: * @param fact Factory that is used for creation. If null is passed it searches for
0182: * a factory providing displayable component.
0183: * @param toolbar visibility of toolbar
0184: * @param statusLine visibility of statusLine
0185: */
0186: public HtmlBrowser(Factory fact, boolean toolbar, boolean statusLine) {
0187: init();
0188:
0189: Impl impl = null;
0190: Component comp = null;
0191:
0192: try {
0193: if (fact == null) {
0194: Impl[] arr = new Impl[1];
0195: comp = findComponent(arr);
0196: impl = arr[0];
0197: } else {
0198: try {
0199: impl = fact.createHtmlBrowserImpl();
0200: comp = impl.getComponent();
0201: } catch (UnsupportedOperationException ex) {
0202: Exceptions.printStackTrace(ex);
0203: impl = new SwingBrowserImpl();
0204: comp = impl.getComponent();
0205: }
0206: }
0207: } catch (RuntimeException e) {
0208: // browser was uninstlled ?
0209: Exceptions.attachLocalizedMessage(e, NbBundle.getMessage(
0210: HtmlBrowser.class, "EXC_Module"));
0211: Exceptions.printStackTrace(e);
0212: }
0213:
0214: browserImpl = impl;
0215: browserComponent = comp;
0216:
0217: setLayout(new BorderLayout(0, 2));
0218:
0219: add((browserComponent != null) ? new JScrollPane(
0220: browserComponent) : new JScrollPane(), "Center"); // NOI18N
0221:
0222: browserListener = new BrowserListener();
0223:
0224: if (toolbar) {
0225: initToolbar();
0226: }
0227:
0228: if (statusLine) {
0229: initStatusLine();
0230: }
0231:
0232: browserImpl.addPropertyChangeListener(browserListener);
0233:
0234: getAccessibleContext().setAccessibleName(
0235: NbBundle.getMessage(HtmlBrowser.class,
0236: "ACS_HtmlBrowser"));
0237: getAccessibleContext().setAccessibleDescription(
0238: NbBundle.getMessage(HtmlBrowser.class,
0239: "ACSD_HtmlBrowser"));
0240: }
0241:
0242: /** Sets the home page.
0243: * @param u the home page
0244: */
0245: public static void setHomePage(String u) {
0246: homePage = u;
0247: }
0248:
0249: /** Getter for the home page
0250: * @return the home page
0251: */
0252: public static String getHomePage() {
0253: if (homePage == null) {
0254: return NbBundle.getMessage(HtmlBrowser.class,
0255: "PROP_HomePage");
0256: }
0257:
0258: return homePage;
0259: }
0260:
0261: /**
0262: * Sets a new implementation of browser visual component
0263: * for all HtmlBrowers.
0264: * @deprecated Use Lookup instead to register factories
0265: */
0266: public static void setFactory(Factory brFactory) {
0267: browserFactory = brFactory;
0268: }
0269:
0270: /** Find Impl of HtmlBrowser. Searches for registered factories in lookup folder.
0271: * Tries to create Impl and check if it provides displayable component.
0272: * Both Component and used Impl are returned to avoid resource consuming of new
0273: * Component/Impl.
0274: * </P>
0275: * <P>
0276: * If no browser is found then it tries to use registered factory (now deprecated method
0277: * of setting browser) or it uses browser based on swing editor in the worst case.
0278: *
0279: * @param handle used browser implementation is in first element when method
0280: * is finished
0281: * @return Component for content displaying
0282: */
0283: private static Component findComponent(Impl[] handle) {
0284: Lookup.Result<Factory> r = Lookup.getDefault().lookup(
0285: new Lookup.Template<Factory>(Factory.class));
0286: for (Factory f : r.allInstances()) {
0287:
0288: try {
0289: Impl impl = f.createHtmlBrowserImpl();
0290: Component c = (impl != null) ? impl.getComponent()
0291: : null;
0292:
0293: if (c != null) {
0294: handle[0] = impl;
0295:
0296: return c;
0297: }
0298: } catch (UnsupportedOperationException ex) {
0299: // do nothing: thrown if browser doesn't work on given platform
0300: }
0301: }
0302:
0303: // 1st fallback to our deprecated method
0304: Factory f = browserFactory;
0305:
0306: if (f != null) {
0307: try {
0308: handle[0] = f.createHtmlBrowserImpl();
0309:
0310: return handle[0].getComponent();
0311: } catch (UnsupportedOperationException ex) {
0312: // do nothing: thrown if browser doesn't work on given platform
0313: }
0314: }
0315:
0316: // last fallback is to swing
0317: handle[0] = new SwingBrowserImpl();
0318:
0319: return handle[0].getComponent();
0320: }
0321:
0322: /**
0323: * Default initializations.
0324: */
0325: private void init() {
0326: try {
0327: if (iBack != null) {
0328: return;
0329: }
0330: iBack = new javax.swing.ImageIcon(
0331: ImageIO
0332: .read(org.openide.awt.HtmlBrowser.class
0333: .getResource("/org/openide/resources/html/back.gif"))); // NOI18N
0334: iForward = new javax.swing.ImageIcon(
0335: ImageIO
0336: .read(org.openide.awt.HtmlBrowser.class
0337: .getResource("/org/openide/resources/html/forward.gif"))); // NOI18N
0338: iHome = new javax.swing.ImageIcon(
0339: ImageIO
0340: .read(org.openide.awt.HtmlBrowser.class
0341: .getResource("/org/openide/resources/html/home.gif"))); // NOI18N
0342: iReload = new javax.swing.ImageIcon(
0343: ImageIO
0344: .read(org.openide.awt.HtmlBrowser.class
0345: .getResource("/org/openide/resources/html/refresh.gif"))); // NOI18N
0346: iStop = new javax.swing.ImageIcon(
0347: ImageIO
0348: .read(org.openide.awt.HtmlBrowser.class
0349: .getResource("/org/openide/resources/html/stop.gif"))); // NOI18N
0350: iHistory = new javax.swing.ImageIcon(
0351: ImageIO
0352: .read(org.openide.awt.HtmlBrowser.class
0353: .getResource("/org/openide/resources/html/history.gif"))); // NOI18N
0354: } catch (IOException ex) {
0355: Logger.getLogger(HtmlBrowser.class.getName())
0356: .log(java.util.logging.Level.SEVERE,
0357: ex.getMessage(), ex);
0358: }
0359: }
0360:
0361: /**
0362: * Default initialization of toolbar.
0363: */
0364: private void initToolbar() {
0365: toolbarVisible = true;
0366:
0367: // create visual compoments .............................
0368: head = new JPanel();
0369: head.setLayout(new BorderLayout(11, 0));
0370:
0371: JPanel p = new JPanel(new GridBagLayout());
0372: p.add(bBack = new JButton(iBack));
0373: bBack.setToolTipText(NbBundle.getMessage(HtmlBrowser.class,
0374: "CTL_Back"));
0375:
0376: GridBagConstraints gbc = new GridBagConstraints();
0377: gbc.insets = new Insets(0, 0, 0, 5);
0378: p.add(bForward = new JButton(iForward), gbc);
0379: bForward.setToolTipText(NbBundle.getMessage(HtmlBrowser.class,
0380: "CTL_Forward"));
0381: p.add(bStop = new JButton(iStop));
0382: bStop.setToolTipText(NbBundle.getMessage(HtmlBrowser.class,
0383: "CTL_Stop"));
0384: gbc = new GridBagConstraints();
0385: gbc.insets = new Insets(0, 0, 0, 5);
0386: p.add(bReload = new JButton(iReload), gbc);
0387: bReload.setToolTipText(NbBundle.getMessage(HtmlBrowser.class,
0388: "CTL_Reload"));
0389: p.add(bHome = new JButton(iHome));
0390: bHome.setToolTipText(NbBundle.getMessage(HtmlBrowser.class,
0391: "CTL_Home"));
0392: gbc = new GridBagConstraints();
0393: gbc.insets = new Insets(0, 0, 0, 5);
0394: p.add(bHistory = new JButton(iHistory), gbc);
0395: bHistory.setToolTipText(NbBundle.getMessage(HtmlBrowser.class,
0396: "CTL_History"));
0397:
0398: if (browserImpl != null) {
0399: bBack.setEnabled(browserImpl.isBackward());
0400: bForward.setEnabled(browserImpl.isForward());
0401: bHistory.setEnabled(browserImpl.isHistory());
0402: }
0403:
0404: JToolBar.Separator ts = new JToolBar.Separator();
0405: gbc = new GridBagConstraints();
0406: gbc.insets = new Insets(0, 0, 0, 5);
0407: p.add(ts, gbc);
0408: ts.updateUI();
0409: p.add(cbLabel = new JLabel());
0410: Mnemonics.setLocalizedText(cbLabel, NbBundle.getMessage(
0411: HtmlBrowser.class, "CTL_Location")); // NOI18N
0412: head.add("West", p); // NOI18N
0413:
0414: head.add("Center", cbLocation = new JComboBox()); // NOI18N
0415: cbLocation.setEditable(true);
0416: cbLabel.setLabelFor(cbLocation);
0417: add(head, "North"); // NOI18N
0418:
0419: // add listeners ..................... .............................
0420: cbLocation.addActionListener(browserListener);
0421: bHistory.addActionListener(browserListener);
0422: bBack.addActionListener(browserListener);
0423: bForward.addActionListener(browserListener);
0424: bReload.addActionListener(browserListener);
0425: bHome.addActionListener(browserListener);
0426: bStop.addActionListener(browserListener);
0427:
0428: bHistory.getAccessibleContext().setAccessibleName(
0429: bHistory.getToolTipText());
0430: bBack.getAccessibleContext().setAccessibleName(
0431: bBack.getToolTipText());
0432: bForward.getAccessibleContext().setAccessibleName(
0433: bForward.getToolTipText());
0434: bReload.getAccessibleContext().setAccessibleName(
0435: bReload.getToolTipText());
0436: bHome.getAccessibleContext().setAccessibleName(
0437: bHome.getToolTipText());
0438: bStop.getAccessibleContext().setAccessibleName(
0439: bStop.getToolTipText());
0440: cbLocation.getAccessibleContext().setAccessibleDescription(
0441: NbBundle.getMessage(HtmlBrowser.class,
0442: "ACSD_HtmlBrowser_Location"));
0443: }
0444:
0445: /**
0446: * Default initialization of toolbar.
0447: */
0448: private void destroyToolbar() {
0449: remove(head);
0450: head = null;
0451: toolbarVisible = false;
0452: }
0453:
0454: /**
0455: * Default initialization of status line.
0456: */
0457: private void initStatusLine() {
0458: statusLineVisible = true;
0459: add(lStatusLine = new JLabel(NbBundle.getMessage(
0460: HtmlBrowser.class, "CTL_Loading")), "South" // NOI18N
0461: );
0462: lStatusLine.setLabelFor(this );
0463: }
0464:
0465: /**
0466: * Destroyes status line.
0467: */
0468: private void destroyStatusLine() {
0469: remove(lStatusLine);
0470: lStatusLine = null;
0471: statusLineVisible = false;
0472: }
0473:
0474: // public methods ............................................................
0475:
0476: /**
0477: * Sets new URL.
0478: *
0479: * @param str URL to show in this browser.
0480: */
0481: public void setURL(String str) {
0482: URL URL;
0483:
0484: try {
0485: URL = new URL(str);
0486: } catch (MalformedURLException ee) {
0487: try {
0488: URL = new URL("http://" + str); // NOI18N
0489: } catch (MalformedURLException e) {
0490: if (browserImpl instanceof SwingBrowserImpl) {
0491: ((SwingBrowserImpl) browserImpl)
0492: .setStatusText(NbBundle.getMessage(
0493: SwingBrowserImpl.class,
0494: "FMT_InvalidURL",
0495: new Object[] { str }));
0496: } else {
0497: Exceptions.printStackTrace(ee);
0498: }
0499:
0500: return;
0501: }
0502: }
0503:
0504: setURL(URL);
0505: }
0506:
0507: /**
0508: * Sets new URL.
0509: *
0510: * @param url URL to show in this browser.
0511: */
0512: public void setURL(final URL url) {
0513: if (url == null) {
0514: return;
0515: }
0516:
0517: class URLSetter implements Runnable {
0518: private boolean sameHosts = false;
0519:
0520: public void run() {
0521: if (!SwingUtilities.isEventDispatchThread()) {
0522: if ("nbfs".equals(url.getProtocol())) { // NOI18N
0523: sameHosts = true;
0524: } else {
0525: sameHosts = (url.getHost() != null)
0526: && (browserImpl.getURL() != null)
0527: && (url.getHost().equals(browserImpl
0528: .getURL().getHost()));
0529: }
0530:
0531: SwingUtilities.invokeLater(this );
0532: } else {
0533: if (url.equals(browserImpl.getURL()) && sameHosts) { // see bug 9470
0534: browserImpl.reloadDocument();
0535: } else {
0536: browserImpl.setURL(url);
0537: }
0538: }
0539: }
0540: }
0541: rp.getDefault().post(new URLSetter());
0542: }
0543:
0544: /**
0545: * Gets current document url.
0546: */
0547: public final URL getDocumentURL() {
0548: return browserImpl.getURL();
0549: }
0550:
0551: /**
0552: * Enables/disables Home button.
0553: */
0554: public final void setEnableHome(boolean b) {
0555: bHome.setEnabled(b);
0556: bHome.setVisible(b);
0557: }
0558:
0559: /**
0560: * Enables/disables location.
0561: */
0562: public final void setEnableLocation(boolean b) {
0563: cbLocation.setEditable(b);
0564: cbLocation.setVisible(b);
0565: cbLabel.setVisible(b);
0566: }
0567:
0568: /**
0569: * Gets status line state.
0570: */
0571: public boolean isStatusLineVisible() {
0572: return statusLineVisible;
0573: }
0574:
0575: /**
0576: * Shows/hides status line.
0577: */
0578: public void setStatusLineVisible(boolean v) {
0579: if (v == statusLineVisible) {
0580: return;
0581: }
0582:
0583: if (v) {
0584: initStatusLine();
0585: } else {
0586: destroyStatusLine();
0587: }
0588: }
0589:
0590: /**
0591: * Gets status toolbar.
0592: */
0593: public boolean isToolbarVisible() {
0594: return toolbarVisible;
0595: }
0596:
0597: /**
0598: * Shows/hides toolbar.
0599: */
0600: public void setToolbarVisible(boolean v) {
0601: if (v == toolbarVisible) {
0602: return;
0603: }
0604:
0605: if (v) {
0606: initToolbar();
0607: } else {
0608: destroyToolbar();
0609: }
0610: }
0611:
0612: /**
0613: * Get the browser implementation.
0614: * @return the implementation
0615: * @since org.openide/1 4.27
0616: */
0617: public final Impl getBrowserImpl() {
0618: return browserImpl;
0619: }
0620:
0621: /**
0622: * Get the browser component.
0623: * @return a component or null
0624: * @since org.openide/1 4.27
0625: */
0626: public final Component getBrowserComponent() {
0627: return browserComponent;
0628: }
0629:
0630: // helper methods .......................................................................
0631:
0632: /**
0633: * Returns preferred size.
0634: */
0635: public java.awt.Dimension getPreferredSize() {
0636: java.awt.Dimension super Pref = super .getPreferredSize();
0637:
0638: return new java.awt.Dimension(Math.max(DEFAULT_WIDTH,
0639: super Pref.width), Math.max(DEFAULT_HEIGHT,
0640: super Pref.height));
0641: }
0642:
0643: /**
0644: * Show current brower's URL in the location bar combo box.
0645: */
0646: private void updateLocationBar() {
0647: if (toolbarVisible) {
0648: everythinkIListenInCheckBoxIsUnimportant = true;
0649:
0650: URL url = browserImpl.getURL();
0651:
0652: if (url != null) {
0653: cbLocation.setSelectedItem(url.toString());
0654: }
0655:
0656: everythinkIListenInCheckBoxIsUnimportant = false;
0657: }
0658: }
0659:
0660: ////// Accessibility //////
0661: public void requestFocus() {
0662: if (browserComponent != null) {
0663: boolean ownerFound = false;
0664:
0665: if (browserComponent instanceof JComponent) {
0666: ownerFound = ((JComponent) browserComponent)
0667: .requestDefaultFocus();
0668: }
0669:
0670: if (!ownerFound) {
0671: browserComponent.requestFocus();
0672: }
0673: } else {
0674: super .requestFocus();
0675: }
0676: }
0677:
0678: public boolean requestFocusInWindow() {
0679: if (browserComponent != null) {
0680: boolean ownerFound = false;
0681:
0682: if (browserComponent instanceof JComponent) {
0683: ownerFound = ((JComponent) browserComponent)
0684: .requestDefaultFocus();
0685: }
0686:
0687: if (!ownerFound) {
0688: return browserComponent.requestFocusInWindow();
0689: } else {
0690: return true;
0691: }
0692: } else {
0693: return super .requestFocusInWindow();
0694: }
0695: }
0696:
0697: public AccessibleContext getAccessibleContext() {
0698: if (accessibleContext == null) {
0699: accessibleContext = new AccessibleHtmlBrowser();
0700: }
0701:
0702: return accessibleContext;
0703: }
0704:
0705: /**
0706: * Implementation of BrowerFactory creates new instances of some Browser implementation.
0707: *
0708: * @see HtmlBrowser.Impl
0709: */
0710: public interface Factory {
0711: /**
0712: * Returns a new instance of BrowserImpl implementation.
0713: */
0714: public Impl createHtmlBrowserImpl();
0715: }
0716:
0717: // innerclasses ..............................................................
0718:
0719: /**
0720: * Listens on changes in HtmlBrowser.Impl and HtmlBrowser visual components.
0721: */
0722: private class BrowserListener implements ActionListener,
0723: PropertyChangeListener {
0724: BrowserListener() {
0725: }
0726:
0727: /**
0728: * Listens on changes in HtmlBrowser.Impl.
0729: */
0730: public void propertyChange(PropertyChangeEvent evt) {
0731: String property = evt.getPropertyName();
0732:
0733: if (property == null) {
0734: return;
0735: }
0736:
0737: if (property.equals(Impl.PROP_URL)
0738: || property.equals(Impl.PROP_TITLE)) {
0739: HtmlBrowser.this .firePropertyChange(evt
0740: .getPropertyName(), evt.getOldValue(), evt
0741: .getNewValue());
0742: }
0743:
0744: if (property.equals(Impl.PROP_URL)) {
0745: updateLocationBar();
0746: } else if (property.equals(Impl.PROP_STATUS_MESSAGE)) {
0747: String s = browserImpl.getStatusMessage();
0748:
0749: if ((s == null) || (s.length() < 1)) {
0750: s = NbBundle.getMessage(HtmlBrowser.class,
0751: "CTL_Document_done");
0752: }
0753:
0754: if (lStatusLine != null) {
0755: lStatusLine.setText(s);
0756: }
0757: } else if (property.equals(Impl.PROP_FORWARD)
0758: && (bForward != null)) {
0759: bForward.setEnabled(browserImpl.isForward());
0760: } else if (property.equals(Impl.PROP_BACKWARD)
0761: && (bBack != null)) {
0762: bBack.setEnabled(browserImpl.isBackward());
0763: } else if (property.equals(Impl.PROP_HISTORY)
0764: && (bHistory != null)) {
0765: bHistory.setEnabled(browserImpl.isHistory());
0766: }
0767: }
0768:
0769: /**
0770: * Listens on changes in HtmlBrowser visual components.
0771: */
0772: public void actionPerformed(ActionEvent e) {
0773: if (e.getSource() == cbLocation) {
0774: // URL manually changed
0775: if (everythinkIListenInCheckBoxIsUnimportant) {
0776: return;
0777: }
0778:
0779: JComboBox cb = (JComboBox) e.getSource();
0780: Object o = cb.getSelectedItem();
0781:
0782: if (o == null) { // empty combo box
0783:
0784: return;
0785: }
0786:
0787: setURL((String) o);
0788:
0789: ListModel lm = cb.getModel();
0790: int i;
0791: int k = lm.getSize();
0792:
0793: for (i = 0; i < k; i++)
0794: if (o.equals(lm.getElementAt(i))) {
0795: break;
0796: }
0797:
0798: if (i != k) {
0799: return;
0800: }
0801:
0802: if (k == 20) {
0803: cb.removeItem(lm.getElementAt(k - 1));
0804: }
0805:
0806: cb.insertItemAt(o, 0);
0807: } else if (e.getSource() == bHistory) {
0808: browserImpl.showHistory();
0809: } else if (e.getSource() == bBack) {
0810: browserImpl.backward();
0811: } else if (e.getSource() == bForward) {
0812: browserImpl.forward();
0813: } else if (e.getSource() == bReload) {
0814: updateLocationBar();
0815: browserImpl.reloadDocument();
0816: } else if (e.getSource() == bHome) {
0817: setURL(getHomePage());
0818: } else if (e.getSource() == bStop) {
0819: browserImpl.stopLoading();
0820: }
0821: }
0822: }
0823:
0824: /**
0825: * This interface represents an implementation of html browser used in HtmlBrowser. Each BrowserImpl
0826: * implementation corresponds with some BrowserFactory implementation.
0827: */
0828: public static abstract class Impl {
0829: /** generated Serialized Version UID */
0830: static final long serialVersionUID = 2912844785502962114L;
0831:
0832: /** The name of property representing status of html browser. */
0833: public static final String PROP_STATUS_MESSAGE = "statusMessage"; // NOI18N
0834:
0835: /** The name of property representing current URL. */
0836: public static final String PROP_URL = "url"; // NOI18N
0837:
0838: /** Title property */
0839: public static final String PROP_TITLE = "title"; // NOI18N
0840:
0841: /** forward property */
0842: public static final String PROP_FORWARD = "forward"; // NOI18N
0843:
0844: /** backward property name */
0845: public static final String PROP_BACKWARD = "backward"; // NOI18N
0846:
0847: /** history property name */
0848: public static final String PROP_HISTORY = "history"; // NOI18N
0849:
0850: /**
0851: * Returns visual component of html browser.
0852: *
0853: * @return visual component of html browser.
0854: */
0855: public abstract java.awt.Component getComponent();
0856:
0857: /**
0858: * Reloads current html page.
0859: */
0860: public abstract void reloadDocument();
0861:
0862: /**
0863: * Stops loading of current html page.
0864: */
0865: public abstract void stopLoading();
0866:
0867: /**
0868: * Sets current URL.
0869: *
0870: * @param url URL to show in the browser.
0871: */
0872: public abstract void setURL(URL url);
0873:
0874: /**
0875: * Returns current URL.
0876: *
0877: * @return current URL.
0878: */
0879: public abstract URL getURL();
0880:
0881: /**
0882: * Returns status message representing status of html browser.
0883: *
0884: * @return status message.
0885: */
0886: public abstract String getStatusMessage();
0887:
0888: /** Returns title of the displayed page.
0889: * @return title
0890: */
0891: public abstract String getTitle();
0892:
0893: /** Is forward button enabled?
0894: * @return true if it is
0895: */
0896: public abstract boolean isForward();
0897:
0898: /** Moves the browser forward. Failure is ignored.
0899: */
0900: public abstract void forward();
0901:
0902: /** Is backward button enabled?
0903: * @return true if it is
0904: */
0905: public abstract boolean isBackward();
0906:
0907: /** Moves the browser forward. Failure is ignored.
0908: */
0909: public abstract void backward();
0910:
0911: /** Is history button enabled?
0912: * @return true if it is
0913: */
0914: public abstract boolean isHistory();
0915:
0916: /** Invoked when the history button is pressed.
0917: */
0918: public abstract void showHistory();
0919:
0920: /**
0921: * Adds PropertyChangeListener to this browser.
0922: *
0923: * @param l Listener to add.
0924: */
0925: public abstract void addPropertyChangeListener(
0926: PropertyChangeListener l);
0927:
0928: /**
0929: * Removes PropertyChangeListener from this browser.
0930: *
0931: * @param l Listener to remove.
0932: */
0933: public abstract void removePropertyChangeListener(
0934: PropertyChangeListener l);
0935: }
0936:
0937: /** A manager class which can display URLs in the proper way.
0938: * Might open a selected HTML browser, knows about embedded vs. external
0939: * browsers, etc.
0940: * @since 3.14
0941: */
0942: public static abstract class URLDisplayer {
0943: /** Subclass constructor. */
0944: protected URLDisplayer() {
0945: }
0946:
0947: /** Get the default URL displayer.
0948: * @return the default instance from lookup
0949: */
0950: public static URLDisplayer getDefault() {
0951: URLDisplayer dflt = (URLDisplayer) Lookup.getDefault()
0952: .lookup(URLDisplayer.class);
0953:
0954: if (dflt == null) {
0955: // Fallback.
0956: dflt = new TrivialURLDisplayer();
0957: }
0958:
0959: return dflt;
0960: }
0961:
0962: /**
0963: * API clients usage: Call this method to display your URL in some browser.
0964: * Typically for external browsers this method is
0965: * non-blocking, doesn't wait until page gets displayed. Also, failures
0966: * are reported using dialog. However note that as there are other
0967: * implementations of this method, actual behaviour may be different.
0968: *
0969: * <p>
0970: * SPI clients usage: Implement this method to display given URL to the user.
0971: * </p>
0972: *
0973: * @param u the URL to show
0974: */
0975: public abstract void showURL(URL u);
0976: }
0977:
0978: private static final class TrivialURLDisplayer extends URLDisplayer {
0979: public TrivialURLDisplayer() {
0980: }
0981:
0982: public void showURL(URL u) {
0983: HtmlBrowser browser = new HtmlBrowser();
0984: browser.setURL(u);
0985:
0986: JFrame frame = new JFrame();
0987: frame
0988: .setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
0989: frame.getContentPane().add(browser);
0990: frame.pack();
0991: frame.setVisible(true);
0992: }
0993: }
0994:
0995: private class AccessibleHtmlBrowser extends JPanel.AccessibleJPanel {
0996: AccessibleHtmlBrowser() {
0997: }
0998:
0999: public void setAccessibleName(String name) {
1000: super .setAccessibleName(name);
1001:
1002: if (browserComponent instanceof Accessible) {
1003: browserComponent.getAccessibleContext()
1004: .setAccessibleName(name);
1005: }
1006: }
1007:
1008: public void setAccessibleDescription(String desc) {
1009: super .setAccessibleDescription(desc);
1010:
1011: if (browserComponent instanceof Accessible) {
1012: browserComponent.getAccessibleContext()
1013: .setAccessibleDescription(desc);
1014: }
1015: }
1016: }
1017: }
|