⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 webbrowser.java

📁 JDesktop Integration Components (JDIC)
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 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.loadLibrary("jdic");
        }catch(PrivilegedActionException e){
            e.printStackTrace();
        }    
        eventThread = new NativeEventThread();
    }

    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;
                case WebBrowserEvent.WEBBROWSER_DOCUMENT_COMPLETED:
                    listener.documentCompleted(e);
                    break;
                case WebBrowserEvent.WEBBROWSER_TITLE_CHANGE:
                    listener.titleChange(e);
                    break;
                case WebBrowserEvent.WEBBROWSER_STATUSTEXT_CHANGE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -