webbrowser.java
来自「jdic,显著提高swing性能的插件」· Java 代码 · 共 832 行 · 第 1/2 页
JAVA
832 行
/* * Copyright (C) 2004 Sun Microsystems, Inc. All rights reserved. Use is * subject to license terms. * * This program is free software; you can redistribute it and/or modify * it under the terms of the Lesser GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */package org.jdesktop.jdic.browser;import java.util.Vector;import java.net.URL;import java.net.MalformedURLException;import java.awt.*;import java.awt.event.*;import java.security.*;import org.jdesktop.jdic.init.JdicInitException;import org.jdesktop.jdic.init.JdicManager;import org.jdesktop.jdic.browser.internal.WebBrowserUtil;/** * A <code>WebBrowser</code> component represents a blank rectangular area of * the screen onto which the application can display webpages or from which the * application can trap events from the browser window. In order to show <code> * WebBrowser</code> component in GUI, users need to add <code>WebBrowser</code> * to a top-level container, such as <code>Frame</code>. * <p> * The class that is interested in processing a <code>WebBrowser</code> event * should implement interface <code>WebBrowserListener</code>, and the object * created with that class should use WebBrowser's <code>addWebBrowserListener * </code> method to register as a listener. * <p> * As an AWT component, a <code>WebBrowser</code> component must be hosted by * a native container somewhere higher up in the component tree (for example, * by a JPanel object). * * @see WebBrowserEvent * @see WebBrowserListener * * @author Kyle Yuan * @version 0.1, 03/07/17 */public class WebBrowser extends Canvas{ private MyFocusListener focusListener = new MyFocusListener(); // eventThread should be initialized after JdicManager.initShareNative() // in static block. private static NativeEventThread eventThread; private Vector webBrowserListeners = new Vector(); private int instanceNum; private static int lastInstanceNum = 0; // WebBrowser status. private boolean isInitialized = false; private boolean isBackEnabled = false; private boolean isForwardEnabled = false; private String initFailureMessage = "WebBrowser is not initialized."; /** * boolean flag used to indicate how to dispose this instance. * @see #dispose() * @see #removeNotify() */ final private boolean autoDispose; /** * Used to cache the url before dispose this instance. * * @see #dispose() * @see #addNotify() * @see #removeNotify() */ private URL urlBeforeDispose = null; static { // Add the initialization code from package org.jdesktop.jdic.init. // To set the environment variables or initialize the set up for // native libraries and executable files. try { JdicManager jm = JdicManager.getManager(); jm.initShareNative(); jm.initBrowserNative(); } catch (JdicInitException e){ e.printStackTrace(); } eventThread = new NativeEventThread(); AccessController.doPrivileged( new PrivilegedAction() { public Object run() { System.loadLibrary("jdic"); return null; // nothing to return } } ); } void setInitialized(boolean b) { isInitialized = b; } void setInitFailureMessage(String msg) { initFailureMessage = msg; } /** * Constructs a new <code>WebBrowser</code> object with no URL specified. * This instance will automatically dispose itself when <code>removeNotify() * </code> is called. * <p> * This constructor is equivalent to <code>WebBrowser(true)</code>. * * @see #WebBrowser(boolean) * @see #removeNotify() * @see #dispose() */ public WebBrowser() { this(true); } /** * Constructs a new <code>WebBrowser</code> object with the specified * boolean value <code>autoDispose</code> as the flag which indicates * whether this instance will automatically dispose itself in <code> * removeNotify()</code> or should be disposed by the developer directly * calling <code>dispose()</code>. * <p> * This constructor is equivalent to <code>WebBrowser(null, autoDispose) * </code>. * * @param autoDispose ture to indicate this instance will automatically * dispose itself in <code>removeNotify()</code>; false to indicate * the developer should call <code>dispose()</code> when this * instance is no longer needed. * * @see #removeNotify() * @see #dispose() * @see #isAutoDispose() */ public WebBrowser(boolean autoDispose){ this(null, autoDispose); } /** * Constructs a new <code>WebBrowser</code> with an URL specified. This * instance will automatically dispose itself when <code>removeNotify() * </code> is called. * <p>This constructor is equivalent to <code>WebBrowser(url, true)</code>. * @param url the URL to be shown in this instance. * * @see #WebBrowser(boolean) * @see #removeNotify() * @see #dispose() */ public WebBrowser(URL url) { this(url, true); } /** * Constructs a new <code>WebBrowser</code> with an specified URL and * boolean flag to indicate the dispose schema. * * @param url the URL to be shown in this instance. * @param autoDispose ture to indicate this instance will automatically * dispose itself in <code>removeNotify()</code>; false to indicate * the developer should call <code>dispose()</code> when this * instance is no longer needed. * * @see #removeNotify() * @see #dispose() * @see #isAutoDispose() */ public WebBrowser(URL url, boolean autoDispose){ this.autoDispose = autoDispose; synchronized(WebBrowser.class) { instanceNum = lastInstanceNum; lastInstanceNum++; } eventThread.attachWebBrowser(this); if (0 == instanceNum) { eventThread.start(); eventThread.fireNativeEvent(instanceNum, NativeEventData.EVENT_INIT); } if (null != url) { setURL(url); } setFocusable(true); addFocusListener(focusListener); } /** * Creates the peer for this WebBrowser component. The peer allows us to * modify the appearance of the WebBrowser component without changing its * functionality. * * @see #removeNotify() */ public void addNotify() { super.addNotify(); if(!isInitialized) { eventThread.fireNativeEvent(instanceNum, NativeEventData.EVENT_CREATEWINDOW); /** * Reset the URL before this instance was disposed. * urlBeforeDispose is set in {@link #disposed()}. */ if(urlBeforeDispose != null){ this.setURL(urlBeforeDispose); urlBeforeDispose = null; } } if(!autoDispose){ this.setVisible(true); } } /** * Makes this WebBrowser component undisplayable by destroying it native * screen resource if the <code>isAutoDispose()</code> returns true. Or just * make this instance invisible if the <code>isAutoDispose()</code> return * false. <p> * This method is called by the toolkit internally and should not be called * directly by programs. * <p> * If <code>isAutoDispose()</code> return false, developer should call * <code>dispose()</code> when this instance is no longer needed. * Otherwise, it resource will never be released untill this JVM exit. * * @see #addNotify() * @see #dispose() * @see #isAutoDispose() */ public void removeNotify() { if(autoDispose){ dispose(); }else{ this.setVisible(false); } } /** * Release this instance's resource and make it undisplayable. If <code> * isAutoDispose()</code> return true, this method will be called by the * toolkit internally. If <code>isAutoDispose()</code> return false, this * method should be called by developer when this instance is no longer * needed. * * @see #removeNotify() * @see #isAutoDispose() */ public void dispose() { urlBeforeDispose = this.getURL(); Thread disposeThread = new Thread() { public void run() { synchronized( WebBrowser.this ){ eventThread.fireNativeEvent(instanceNum, NativeEventData.EVENT_DESTROYWINDOW); try { // wait untill we get the message // WebBrowserEvent.WEBBROWSER_DESTROYWINDOW_SUCC // from native process. WebBrowser.this.wait(); } catch (InterruptedException e) { } } WebBrowser.super.removeNotify(); setInitialized(false); } }; disposeThread.start(); } /** * Return the boolean flag which indicates how to dispose this instance. * * @return true if this instance should be disposed by itself when * <code>removeNotify()</code> is called. false if this instance * should be disposed by the developer directly calling * <code>dispose()</code> when it is no longer needed. * * @see #removeNotify() * @see #addNotify() * @see #dispose() */ public boolean isAutoDispose(){ return autoDispose; } /** * Moves and resizes this component. The new location of the top-left * corner is specified by <code>x</code> and <code>y</code>, and the new * size is specified by <code>width</code> and <code>height</code>. * * @param x - the new x-coordinate of this component * @param y - the new y-coordinate of this component * @param width - the new width of this component * @param height - the new height of this component */ public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); eventThread.fireNativeEvent(instanceNum, NativeEventData.EVENT_SET_BOUNDS, new Rectangle(x, y, width, height)); } /* * Dispatches a WebBrowserEvent to the Java embeddor, called by * NativeEventThread.processIncomingMessage. */ void dispatchWebBrowserEvent(WebBrowserEvent e) { int eid = e.getID(); WebBrowserUtil.trace("Got event from NativeEventThread " + eid); // native browser needs immediate return value for these two events. // Special trigger messages beginning with a '@' character, to give // the native browser a yes or no to continue an operation(navigating // an URL or openning a new window). String msg = "@" + instanceNum + "," + eid + ","; if (WebBrowserEvent.WEBBROWSER_BEFORE_NAVIGATE == eid) { URL url = null; try { url = new URL(e.getData()); } catch (MalformedURLException ex1) { try { // IE omits the file:/ protocol for local files, append it. if (!WebBrowserUtil.isDefaultBrowserMozilla()) { url = new URL("file:/" + e.getData()); } } catch (MalformedURLException ex2) { } } msg += willOpenURL(url) ? "0" : "1"; eventThread.messenger.sendMessage(msg); return; } else if (WebBrowserEvent.WEBBROWSER_BEFORE_NEWWINDOW == eid) { msg += willOpenWindow() ? "0" : "1"; eventThread.messenger.sendMessage(msg); return; } else if (WebBrowserEvent.WEBBROWSER_COMMAND_STATE_CHANGE == eid) { String data = e.getData(); if (data.startsWith("forward")) { isForwardEnabled = data.substring(8).equals("1"); WebBrowserUtil.trace("Forward State changed = " + isForwardEnabled); } else if (data.startsWith("back")) { isBackEnabled = data.substring(5).equals("1"); WebBrowserUtil.trace("Back State changed = " + isBackEnabled); } return; } else if (WebBrowserEvent.WEBBROWSER_FOCUS_REQUEST == eid) { WebBrowserUtil.trace("Got event from brower: Focus request."); requestFocus(); return; } else if (WebBrowserEvent.WEBBROWSER_DESTROYWINDOW_SUCC == eid){ WebBrowserUtil.trace("Got event from brower: Destory window " + "succeeds."); synchronized(this){ // notify the disposeThread in removeNotify(). this.notify(); } } // for the normal case, call the corresponding method in listeners. int size; Vector tl; synchronized (this) { size = webBrowserListeners.size(); if (size == 0) { return; } tl = (Vector) webBrowserListeners.clone(); } for (int i = 0; i < size; ++i) { WebBrowserListener listener = (WebBrowserListener) tl.elementAt(i); switch (eid) { case WebBrowserEvent.WEBBROWSER_DOWNLOAD_STARTED: listener.downloadStarted(e); break; case WebBrowserEvent.WEBBROWSER_DOWNLOAD_COMPLETED: listener.downloadCompleted(e); break; case WebBrowserEvent.WEBBROWSER_DOWNLOAD_PROGRESS: listener.downloadProgress(e); break; case WebBrowserEvent.WEBBROWSER_DOWNLOAD_ERROR: listener.downloadError(e); break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?