org.openide.awt.HtmlBrowser Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.openide.awt;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
import org.openide.util.*;
/**
* Object that provides viewer for HTML pages.
* If all you want to do is to show some URL, this
* is overkill. Just use {@link HtmlBrowser.URLDisplayer#showURL} instead. Using HtmlBrowser
* is appropriate mainly if you want to embed a web browser in some other GUI component
* (if the user has selected an external browser, this will fall back to a simple Swing
* renderer). Similarly Impl
(coming from a Factory
) is the lower-level
* renderer itself (sans toolbar).
*
Summary: for client use, try URLDisplayer.showURL
, or for more control
* or where embedding is needed, create an HtmlBrowser
. For provider use,
* create a Factory
and register an instance of it to lookup.
*/
public class HtmlBrowser extends JPanel {
// static ....................................................................
/** generated Serialized Version UID */
private static final long serialVersionUID = 2912844785502987960L;
/** Preferred width of the browser */
public static final int DEFAULT_WIDTH = 400;
/** Preferred height of the browser */
public static final int DEFAULT_HEIGHT = 600;
/** current implementation of html browser */
private static Factory browserFactory;
/** home page URL */
private static String homePage = null;
// variables .................................................................
/** currently used implementation of browser */
final Impl browserImpl;
/** true = ignore changes in location field */
private boolean ignoreChangeInLocationField = false;
/** toolbar visible property */
private boolean toolbarVisible = false;
/** status line visible property */
private boolean statusLineVisible = false;
/** Listens on changes in HtmlBrowser.Impl and HtmlBrowser visual components.
*/
private BrowserListener browserListener;
// visual components .........................................................
private JButton bBack;
// visual components .........................................................
private JButton bForward;
// visual components .........................................................
private JButton bReload;
// visual components .........................................................
private JButton bStop;
/** URL chooser */
private JTextField txtLocation;
private JLabel lStatusLine;
final Component browserComponent;
private JPanel head;
private RequestProcessor rp = new RequestProcessor();
private final Component extraToolbar;
// init ......................................................................
/**
* Creates new html browser with toolbar and status line.
*/
public HtmlBrowser() {
this(true, true);
}
/**
* Creates new html browser.
*
* @param toolbar visibility of toolbar
* @param statusLine visibility of statusLine
*/
public HtmlBrowser(boolean toolbar, boolean statusLine) {
this(null, toolbar, statusLine);
}
/**
* Creates new html browser.
*
* @param fact Factory that is used for creation. If null is passed it searches for
* a factory providing displayable component.
* @param toolbar visibility of toolbar
* @param statusLine visibility of statusLine
*/
public HtmlBrowser(Factory fact, boolean toolbar, boolean statusLine) {
this( fact, toolbar, statusLine, null );
}
/**
* Creates new html browser.
*
* @param fact Factory that is used for creation. If null is passed it searches for
* a factory providing displayable component.
* @param toolbar visibility of toolbar
* @param statusLine visibility of statusLine
* @param extraToolbar Additional toolbar to be displayed under the default
* toolbar with location field and back/forward buttons.
* @since 7.52
*/
public HtmlBrowser(Factory fact, boolean toolbar, boolean statusLine, Component extraToolbar) {
Impl impl = null;
Component comp = null;
try {
if (fact == null) {
Impl[] arr = new Impl[1];
comp = findComponent(arr);
impl = arr[0];
} else {
try {
impl = fact.createHtmlBrowserImpl();
comp = impl.getComponent();
} catch (UnsupportedOperationException ex) {
Exceptions.printStackTrace(ex);
impl = new SwingBrowserImpl();
comp = impl.getComponent();
}
}
} catch (RuntimeException e) {
// browser was uninstlled ?
Exceptions.attachLocalizedMessage(e,
NbBundle.getMessage(HtmlBrowser.class,
"EXC_Module"));
Exceptions.printStackTrace(e);
}
browserImpl = impl;
browserComponent = comp;
this.extraToolbar = extraToolbar;
setLayout(new BorderLayout(0, 2));
add((browserComponent != null) ? browserComponent : new JScrollPane(), "Center"); // NOI18N
browserListener = new BrowserListener();
if (toolbar) {
initToolbar();
}
if (statusLine) {
initStatusLine();
}
browserImpl.addPropertyChangeListener(browserListener);
getAccessibleContext().setAccessibleName(NbBundle.getMessage(HtmlBrowser.class, "ACS_HtmlBrowser"));
getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(HtmlBrowser.class, "ACSD_HtmlBrowser"));
}
/** Sets the home page.
* @param u the home page
*/
public static void setHomePage(String u) {
homePage = u;
}
/** Getter for the home page
* @return the home page
*/
public static String getHomePage() {
if (homePage == null) {
return NbBundle.getMessage(HtmlBrowser.class, "PROP_HomePage");
}
return homePage;
}
/**
* Sets a new implementation of browser visual component
* for all HtmlBrowers.
* @deprecated Use Lookup instead to register factories
*/
@Deprecated
public static void setFactory(Factory brFactory) {
browserFactory = brFactory;
}
/** Find Impl of HtmlBrowser. Searches for registered factories in lookup folder.
* Tries to create Impl and check if it provides displayable component.
* Both Component and used Impl are returned to avoid resource consuming of new
* Component/Impl.
*
*
* If no browser is found then it tries to use registered factory (now deprecated method
* of setting browser) or it uses browser based on swing editor in the worst case.
*
* @param handle used browser implementation is in first element when method
* is finished
* @return Component for content displaying
*/
private static Component findComponent(Impl[] handle) {
Lookup.Result r = Lookup.getDefault().lookup(new Lookup.Template(Factory.class));
for (Factory f: r.allInstances()) {
try {
Impl impl = f.createHtmlBrowserImpl();
Component c = (impl != null) ? impl.getComponent() : null;
if (c != null) {
handle[0] = impl;
return c;
}
} catch (UnsupportedOperationException ex) {
// do nothing: thrown if browser doesn't work on given platform
}
}
// 1st fallback to our deprecated method
Factory f = browserFactory;
if (f != null) {
try {
handle[0] = f.createHtmlBrowserImpl();
return handle[0].getComponent();
} catch (UnsupportedOperationException ex) {
// do nothing: thrown if browser doesn't work on given platform
}
}
// last fallback is to swing
handle[0] = new SwingBrowserImpl();
return handle[0].getComponent();
}
/**
* Default initialization of toolbar.
*/
private void initToolbar() {
toolbarVisible = true;
// create visual compoments .............................
head = new JPanel(new GridBagLayout());
bBack = new JButton();
bBack.setBorder(BorderFactory.createEmptyBorder());
bBack.setBorderPainted(false);
bBack.setContentAreaFilled(false);
bBack.setIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/back_normal.png", true)); //NOI18N
bBack.setRolloverIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/back_hover.png", true)); //NOI18N
bBack.setDisabledIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/back_disabled.png", true)); //NOI18N
bBack.setSelectedIcon(bBack.getIcon());
bBack.setToolTipText(NbBundle.getMessage(HtmlBrowser.class, "CTL_Back")); //NOI18N
bForward = new JButton();
bForward.setBorder(BorderFactory.createEmptyBorder());
bForward.setBorderPainted(false);
bForward.setContentAreaFilled(false);
bForward.setIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/forward_normal.png", true)); //NOI18N
bForward.setRolloverIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/forward_hover.png", true)); //NOI18N
bForward.setDisabledIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/forward_disabled.png", true)); //NOI18N
bForward.setSelectedIcon(bForward.getIcon());
bForward.setToolTipText(NbBundle.getMessage(HtmlBrowser.class, "CTL_Forward")); //NOI18N
bReload = new JButton();
bReload.setBorder(BorderFactory.createEmptyBorder());
bReload.setBorderPainted(false);
bReload.setContentAreaFilled(false);
bReload.setIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/refresh.png", true)); //NOI18N
bReload.setRolloverIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/refresh_hover.png", true)); //NOI18N
bReload.setDisabledIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/refresh.png", true)); //NOI18N
bReload.setSelectedIcon(bReload.getIcon());
bReload.setToolTipText(NbBundle.getMessage(HtmlBrowser.class, "CTL_Reload")); //NOI18N
bReload.setFocusPainted(false);
bStop = new JButton();
bStop.setBorderPainted(false);
bStop.setBorder(BorderFactory.createEmptyBorder());
bStop.setContentAreaFilled(false);
bStop.setIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/stop.png", true)); //NOI18N
bStop.setRolloverIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/stop_hover.png", true)); //NOI18N
bStop.setDisabledIcon(ImageUtilities.loadImageIcon("org/openide/resources/html/stop.png", true)); //NOI18N
bStop.setSelectedIcon(bStop.getIcon());
bStop.setToolTipText(NbBundle.getMessage(HtmlBrowser.class, "CTL_Stop")); //NOI18N
bStop.setFocusPainted(false);
txtLocation = new JTextField();
txtLocation.setEditable(true);
txtLocation.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if( e.getClickCount() == 1 ) {
if( null != txtLocation.getSelectedText()
|| txtLocation.isFocusOwner() )
return;
txtLocation.selectAll();
}
}
});
head.add(bBack, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,1), 0, 0));
head.add(bForward, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0,0,0,4), 0, 0));
head.add(txtLocation, new GridBagConstraints(2, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,4), 0, 0));
head.add(bReload, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,0,0,4), 0, 0));
head.add(bStop, new GridBagConstraints(4, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0,0,0,0), 0, 0));
if( null != extraToolbar ) {
head.add(extraToolbar, new GridBagConstraints(0, 1, 5, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(3,0,0,0), 0, 0));
}
head.setBorder( BorderFactory.createEmptyBorder(8, 10, null == extraToolbar ? 8 : 3, 10));
if (browserImpl != null) {
bBack.setEnabled(browserImpl.isBackward());
bForward.setEnabled(browserImpl.isForward());
}
// add listeners ..................... .............................
txtLocation.addActionListener(browserListener);
bBack.addActionListener(browserListener);
bForward.addActionListener(browserListener);
bReload.addActionListener(browserListener);
bStop.addActionListener(browserListener);
bBack.getAccessibleContext().setAccessibleName(bBack.getToolTipText());
bForward.getAccessibleContext().setAccessibleName(bForward.getToolTipText());
bReload.getAccessibleContext().setAccessibleName(bReload.getToolTipText());
bStop.getAccessibleContext().setAccessibleName(bStop.getToolTipText());
txtLocation.getAccessibleContext().setAccessibleDescription(
NbBundle.getMessage(HtmlBrowser.class, "ACSD_HtmlBrowser_Location")
);
add(head, BorderLayout.NORTH);
}
/**
* Default initialization of toolbar.
*/
private void destroyToolbar() {
remove(head);
head = null;
toolbarVisible = false;
}
/**
* Default initialization of status line.
*/
private void initStatusLine() {
statusLineVisible = true;
add(lStatusLine = new JLabel(NbBundle.getMessage(HtmlBrowser.class, "CTL_Loading")), "South" // NOI18N
);
lStatusLine.setLabelFor(this);
}
/**
* Destroyes status line.
*/
private void destroyStatusLine() {
remove(lStatusLine);
lStatusLine = null;
statusLineVisible = false;
}
// public methods ............................................................
/**
* Sets new URL.
*
* @param str URL to show in this browser.
*/
public void setURL(String str) {
if( null != str ) {
try {
str = new URL(str).toExternalForm();
} catch( ThreadDeath td ) {
throw td;
} catch( Throwable e ) {
//ignore
}
}
browserImpl.setLocation(str);
}
/**
* Sets new URL.
*
* @param url URL to show in this browser.
*/
public void setURL(final URL url) {
if (url == null) {
txtLocation.setText(null);
return;
}
class URLSetter implements Runnable {
private boolean doReload = false;
@Override
public void run() {
if (!SwingUtilities.isEventDispatchThread()) {
boolean sameHosts = false;
if ("nbfs".equals(url.getProtocol())) { // NOI18N
sameHosts = true;
} else {
sameHosts = (url.getHost() != null) && (browserImpl.getURL() != null) &&
(url.getHost().equals(browserImpl.getURL().getHost()));
}
doReload = sameHosts && url.equals(browserImpl.getURL()); // see bug 9470
SwingUtilities.invokeLater(this);
} else {
if (doReload) {
browserImpl.reloadDocument();
} else {
browserImpl.setURL(url);
}
}
}
}
rp.post(new URLSetter());
}
/**
* Gets current document url.
* @return
*/
public final URL getDocumentURL() {
return browserImpl.getURL();
}
/**
* Enables/disables Home button.
* @param b
*/
public final void setEnableHome(boolean b) {
}
/**
* Enables/disables location.
* @param b
*/
public final void setEnableLocation(boolean b) {
txtLocation.setEnabled(b);
txtLocation.setVisible(b);
}
/**
* Gets status line state.
* @return
*/
public boolean isStatusLineVisible() {
return statusLineVisible;
}
/**
* Shows/hides status line.
* @param v
*/
public void setStatusLineVisible(boolean v) {
if (v == statusLineVisible) {
return;
}
if (v) {
initStatusLine();
} else {
destroyStatusLine();
}
}
/**
* Gets status toolbar.
* @return
*/
public boolean isToolbarVisible() {
return toolbarVisible;
}
/**
* Shows/hides toolbar.
* @param v
*/
public void setToolbarVisible(boolean v) {
if (v == toolbarVisible) {
return;
}
if (v) {
initToolbar();
} else {
destroyToolbar();
}
}
/**
* Get the browser implementation.
* @return the implementation
* @since org.openide/1 4.27
*/
public final Impl getBrowserImpl() {
return browserImpl;
}
/**
* Get the browser component.
* @return a component or null
* @since org.openide/1 4.27
*/
public final Component getBrowserComponent() {
return browserComponent;
}
// helper methods .......................................................................
/**
* Returns preferred size.
*/
@Override
public java.awt.Dimension getPreferredSize() {
java.awt.Dimension superPref = super.getPreferredSize();
return new java.awt.Dimension(
Math.max(DEFAULT_WIDTH, superPref.width), Math.max(DEFAULT_HEIGHT, superPref.height)
);
}
/**
* Show current brower's URL in the location bar combo box.
*/
private void updateLocationBar() {
if (toolbarVisible) {
ignoreChangeInLocationField = true;
String url = browserImpl.getLocation();
txtLocation.setText(url);
ignoreChangeInLocationField = false;
}
}
////// Accessibility //////
@Override
public void requestFocus() {
if (browserComponent != null) {
boolean ownerFound = false;
if (browserComponent instanceof JComponent) {
ownerFound = ((JComponent) browserComponent).requestDefaultFocus();
}
if (!ownerFound) {
browserComponent.requestFocus();
}
} else {
super.requestFocus();
}
}
@Override
public boolean requestFocusInWindow() {
if (browserComponent != null) {
boolean ownerFound = false;
if (browserComponent instanceof JComponent) {
ownerFound = ((JComponent) browserComponent).requestDefaultFocus();
}
if (!ownerFound) {
return browserComponent.requestFocusInWindow();
} else {
return true;
}
} else {
return super.requestFocusInWindow();
}
}
@Override
public AccessibleContext getAccessibleContext() {
if (accessibleContext == null) {
accessibleContext = new AccessibleHtmlBrowser();
}
return accessibleContext;
}
/**
* Implementation of BrowerFactory creates new instances of some Browser implementation.
*
* @see HtmlBrowser.Impl
*/
public interface Factory {
/**
* Returns a new instance of BrowserImpl implementation.
* @return
*/
public Impl createHtmlBrowserImpl();
}
// innerclasses ..............................................................
/**
* Listens on changes in HtmlBrowser.Impl and HtmlBrowser visual components.
*/
private class BrowserListener implements ActionListener, PropertyChangeListener {
BrowserListener() {
}
/**
* Listens on changes in HtmlBrowser.Impl.
*/
@Override
public void propertyChange(final PropertyChangeEvent evt) {
String property = evt.getPropertyName();
if (property == null) {
return;
}
if (property.equals(Impl.PROP_URL) || property.equals(Impl.PROP_TITLE)) {
HtmlBrowser.this.firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
}
if (EventQueue.isDispatchThread()) {
propertyChangeInAWT(evt);
} else {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
propertyChangeInAWT(evt);
}
});
}
}
private void propertyChangeInAWT(PropertyChangeEvent evt) {
String property = evt.getPropertyName();
if (property.equals(Impl.PROP_URL)) {
updateLocationBar();
} else if (property.equals(Impl.PROP_STATUS_MESSAGE)) {
String s = browserImpl.getStatusMessage();
if ((s == null) || (s.length() < 1)) {
s = NbBundle.getMessage(HtmlBrowser.class, "CTL_Document_done");
}
if (lStatusLine != null) {
lStatusLine.setText(s);
}
} else if (property.equals(Impl.PROP_FORWARD) && (bForward != null)) {
bForward.setEnabled(browserImpl.isForward());
} else if (property.equals(Impl.PROP_BACKWARD) && (bBack != null)) {
bBack.setEnabled(browserImpl.isBackward());
} else if (property.equals(Impl.PROP_LOADING) && (bStop != null)) {
bStop.setEnabled(((Boolean)evt.getNewValue()).booleanValue());
}
}
/**
* Listens on changes in HtmlBrowser visual components.
*/
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == txtLocation) {
// URL manually changed
if (ignoreChangeInLocationField) {
return;
}
String txt = txtLocation.getText();
if (txt == null || txt.length() == 0) { // empty combo box
return;
}
setURL(txt);
} else
if (e.getSource() == bBack) {
browserImpl.backward();
} else
if (e.getSource() == bForward) {
browserImpl.forward();
} else
if (e.getSource() == bReload) {
updateLocationBar();
browserImpl.reloadDocument();
} else
if (e.getSource() == bStop) {
browserImpl.stopLoading();
}
}
}
/**
* This interface represents an implementation of html browser used in HtmlBrowser. Each BrowserImpl
* implementation corresponds with some BrowserFactory implementation.
*/
public abstract static class Impl {
/** generated Serialized Version UID */
static final long serialVersionUID = 2912844785502962114L;
/** The name of property representing status of html browser. */
public static final String PROP_STATUS_MESSAGE = "statusMessage"; // NOI18N
/** The name of property representing current URL. */
public static final String PROP_URL = "url"; // NOI18N
/** Title property */
public static final String PROP_TITLE = "title"; // NOI18N
/** forward property */
public static final String PROP_FORWARD = "forward"; // NOI18N
/** backward property name */
public static final String PROP_BACKWARD = "backward"; // NOI18N
/** history property name */
public static final String PROP_HISTORY = "history"; // NOI18N
public static final String PROP_BROWSER_WAS_CLOSED = "browser.was.closed"; // NOI18N
/**
* Name of boolean property which is fired when the browser is busy loading
* its content.
*
* @since 7.52
*/
public static final String PROP_LOADING = "loading"; //NOI18N
/**
* Returns visual component of html browser.
*
* @return visual component of html browser.
*/
public abstract java.awt.Component getComponent();
/**
* Reloads current html page.
*/
public abstract void reloadDocument();
/**
* Stops loading of current html page.
*/
public abstract void stopLoading();
/**
* Sets current URL.
*
* @param url URL to show in the browser.
*/
public abstract void setURL(URL url);
/**
* Returns current URL.
*
* @return current URL.
*/
public abstract URL getURL();
/**
* Retrieve current browser location. It doesn't have to be a valid URL,
* e.g. "about:config".
* @return Browser location or null.
* @since 7.13
*/
public String getLocation() {
URL url = getURL();
return null == url ? null : url.toString();
}
/**
* Change current browser location.
* @param location New location to show in the browser. It doesn't
* have to be a valid URL, e.g. "about:config" may be accepted as well.
* @since 7.13
*/
public void setLocation( String location ) {
URL url;
try {
url = new URL(location);
} catch (MalformedURLException ee) {
try {
url = new URL("http://" + location); // NOI18N
} catch (MalformedURLException e) {
String errorMessage = NbBundle.getMessage(SwingBrowserImpl.class, "FMT_InvalidURL", new Object[] { location }); //NOI18N
if (this instanceof SwingBrowserImpl) {
((SwingBrowserImpl) this).setStatusText( errorMessage );
} else {
Logger.getLogger(HtmlBrowser.class.getName()).log(Level.INFO, errorMessage, ee);
}
return;
}
}
setURL(url);
}
/**
* Returns status message representing status of html browser.
*
* @return status message.
*/
public abstract String getStatusMessage();
/** Returns title of the displayed page.
* @return title
*/
public abstract String getTitle();
/** Is forward button enabled?
* @return true if it is
*/
public abstract boolean isForward();
/** Moves the browser forward. Failure is ignored.
*/
public abstract void forward();
/** Is backward button enabled?
* @return true if it is
*/
public abstract boolean isBackward();
/** Moves the browser forward. Failure is ignored.
*/
public abstract void backward();
/** Is history button enabled?
* @return true if it is
*/
public abstract boolean isHistory();
/** Invoked when the history button is pressed.
*/
public abstract void showHistory();
/**
* Adds PropertyChangeListener to this browser.
*
* @param l Listener to add.
*/
public abstract void addPropertyChangeListener(PropertyChangeListener l);
/**
* Removes PropertyChangeListener from this browser.
*
* @param l Listener to remove.
*/
public abstract void removePropertyChangeListener(PropertyChangeListener l);
/**
* Method invoked by the infrastructure when the browser component is no
* longer needed. The default implementation does nothing.
* @since 7.11
*/
public void dispose() {
}
/**
* The content of this Lookup will be merged into browser's TopComponent Lookup.
* @return Browser's Lookup
* @since 7.52
*/
public Lookup getLookup() {
return Lookup.EMPTY;
}
}
/** A manager class which can display URLs in the proper way.
* Might open a selected HTML browser, knows about embedded vs. external
* browsers, etc.
* @since 3.14
*/
public abstract static class URLDisplayer {
/** Subclass constructor. */
protected URLDisplayer() {
}
/** Get the default URL displayer.
* @return the default instance from lookup
*/
public static URLDisplayer getDefault() {
URLDisplayer dflt = Lookup.getDefault().lookup(URLDisplayer.class);
if (dflt == null) {
// Fallback.
dflt = new TrivialURLDisplayer();
}
return dflt;
}
/**
* API clients usage: Call this method to display your URL in some browser.
* Typically for external browsers this method is
* non-blocking, doesn't wait until page gets displayed. Also, failures
* are reported using dialog. However note that as there are other
* implementations of this method, actual behaviour may be different.
*
*
* SPI clients usage: Implement this method to display given URL to the user.
*
*
* @param u the URL to show
*/
public abstract void showURL(URL u);
/**
* Attempts to display given URL in preferred external browser.
* The default implementation just delegates to showURL(URL).
* The URL may be still rendered using an internal browser implementation
* if no external browser is available.
*
* @param u the URL to show
* @since 7.14
*/
public void showURLExternal(URL u) {
showURL(u);
}
}
private static final class TrivialURLDisplayer extends URLDisplayer {
public TrivialURLDisplayer() {
}
@Override
public void showURL(URL u) {
if (Desktop.isDesktopSupported()) {
Desktop d = Desktop.getDesktop();
if (d.isSupported(Desktop.Action.BROWSE)) {
try {
d.browse(u.toURI());
return;
} catch (Exception x) {
Logger.getLogger(HtmlBrowser.class.getName()).log(Level.INFO, "Showing: " + u, x);
}
}
}
// Fallback implementation:
HtmlBrowser browser = new HtmlBrowser();
browser.setURL(u);
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.getContentPane().add(browser);
frame.pack();
frame.setVisible(true);
}
}
private class AccessibleHtmlBrowser extends JPanel.AccessibleJPanel {
AccessibleHtmlBrowser() {
}
@Override
public void setAccessibleName(String name) {
super.setAccessibleName(name);
if (browserComponent instanceof Accessible) {
browserComponent.getAccessibleContext().setAccessibleName(name);
}
}
@Override
public void setAccessibleDescription(String desc) {
super.setAccessibleDescription(desc);
if (browserComponent instanceof Accessible) {
browserComponent.getAccessibleContext().setAccessibleDescription(desc);
}
}
}
}