org.eclipse.eclipsemonkey.ui.scriptableView.BrowserView.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.eclipsemonkey.ui.scriptableView.BrowserView.java

Source

/**
 * Copyright (c) 2005-2006 Aptana, Inc.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html. If redistributing this code,
 * this entire header must remain intact.
 */
package org.eclipse.eclipsemonkey.ui.scriptableView;

import java.util.List;
import java.util.Vector;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.plugin.AbstractUIPlugin;

/**
 * @author Paul Colton (Aptana, Inc.)
 *
 */
public abstract class BrowserView extends ViewPart {
    private String partId; //$NON-NLS-1$
    private Browser browser;
    private String url;

    // TODO: Add to plugin strings for localization

    /**
     * Browser_homeButton_tooltip
     */
    public static String Browser_homeButton_tooltip = Messages.BrowserView_Home;

    /**
     * Browser_forwardButton_tooltip
     */
    public static String Browser_forwardButton_tooltip = Messages.BrowserView_NavigateToNextTopic;

    /**
     * Browser_backwardButton_tooltip
     */
    public static String Browser_backwardButton_tooltip = Messages.BrowserView_NavigateToPreviousTopic;

    /**
     * Browser_invalidConfig
     */
    public static String Browser_invalidConfig = Messages.BrowserView_InvalidConfiguration;

    /**
     * urlListener
     */
    protected BrowserIntroPartLocationListener urlListener = new BrowserIntroPartLocationListener(this);

    /**
     * history
     */
    protected History history = new History();

    // Global actions

    /**
     * backAction
     */
    protected Action backAction = new Action() {

        {
            setToolTipText(BrowserView.Browser_backwardButton_tooltip);
            setImageDescriptor(BrowserView.getImageDescriptor("icons/backward_nav_on.gif")); //$NON-NLS-1$
            setDisabledImageDescriptor(BrowserView.getImageDescriptor("icons/backward_nav_off.gif")); //$NON-NLS-1$
        }

        public void run() {
            navigateBackward();
        }
    };

    /**
     * forwardAction
     */
    protected Action forwardAction = new Action() {
        {
            setToolTipText(BrowserView.Browser_forwardButton_tooltip);
            setImageDescriptor(BrowserView.getImageDescriptor("icons/forward_nav_on.gif")); //$NON-NLS-1$
            setDisabledImageDescriptor(BrowserView.getImageDescriptor("icons/forward_nav_off.gif")); //$NON-NLS-1$
        }

        public void run() {
            navigateForward();
        }
    };

    /**
     * Returns the startup URL (to display when this control initially loads
     * 
     * @return String
     */
    public abstract String getStartUrl();

    /**
     * homeAction
     */
    protected Action homeAction = new Action() {
        {
            setToolTipText(BrowserView.Browser_homeButton_tooltip); //$NON-NLS-1$
            setImageDescriptor(BrowserView.getImageDescriptor("icons/home_nav_on.gif")); //$NON-NLS-1$
            setDisabledImageDescriptor(BrowserView.getImageDescriptor("icons/home_nav_off.gif")); //$NON-NLS-1$
        }

        public void run() {
            navigateHome();
        }
    };

    /**
     * The constructor.
     */
    public BrowserView() {
        url = getStartUrl();
        partId = getPartId();
    }

    /**
     * Returns the "part ID" which is used in the contexts.xml file
     * 
     * @return String
     */
    public abstract String getPartId();

    /**
     * @see org.eclipse.ui.IViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento)
     */
    public void init(IViewSite site, IMemento memento) throws PartInitException {
        super.init(site, memento);

        if (memento != null) {
            url = memento.getString(partId);
            sendMessage(url);
        }
    }

    /**
     * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento)
     */
    public void saveState(IMemento memento) {
        if (url != null) {
            memento.putString(partId, url);
        }
    }

    /**
     * This is a callback that will allow us to create the viewer and initialize it.
     * 
     * @param parent
     */
    public void createPartControl(Composite parent) {
        browser = new Browser(parent, SWT.NONE);
        if (this.url != null) {
            browser.setUrl(this.url);
        }

        PlatformUI.getWorkbench().getHelpSystem().setHelp(browser, "com.aptana.ide.js.ui." + partId); //$NON-NLS-1$

        // add a location listener on the browser so we can intercept
        // LocationEvents. Responsible for intercepting URLs and updating UI
        // with history.
        browser.addLocationListener(urlListener);

        // add a location listener that will clear a flag at the end of any
        // navigation to a page. This is used in conjunction with the location
        // listener to filter out redundant navigations due to frames.
        browser.addProgressListener(new ProgressListener() {

            public void changed(ProgressEvent event) {
                // no-op
            }

            public void completed(ProgressEvent event) {
                urlListener.flagEndOfNavigation();
                urlListener.flagEndOfFrameNavigation();
                urlListener.flagRemovedTempUrl();
                updateNavigationActionsState();
            }
        });

        addToolBarActions();
    }

    /*******************************************************************************************************************
     * Pulled from BrowserIntroPartImplementation
     ******************************************************************************************************************/

    protected void addToolBarActions() {

        IActionBars actionBars = getViewSite().getActionBars();

        IToolBarManager toolBarManager = actionBars.getToolBarManager();
        actionBars.setGlobalActionHandler(ActionFactory.FORWARD.getId(), forwardAction);
        actionBars.setGlobalActionHandler(ActionFactory.BACK.getId(), backAction);
        toolBarManager.add(homeAction);
        toolBarManager.add(backAction);
        toolBarManager.add(forwardAction);
        toolBarManager.update(true);
        actionBars.updateActionBars();
        updateNavigationActionsState();
    }

    /**
     * Return a reference to the browser
     * 
     * @return Browser
     */
    public Browser getBrowser() {
        return browser;
    }

    /**
     * Passing the focus request to the viewer's control.
     */
    public void setFocus() {
        browser.setFocus();
    }

    /**
     * @param url 
     */
    public void sendMessage(String url) {
        if (url != null) {
            this.url = url;
            if (browser != null) {
                browser.setUrl(url);
            }
        }
    }

    /**
     * updateNavigationActionsState
     */
    protected void updateNavigationActionsState() {
        // in static html intro, use browser history.
        forwardAction.setEnabled(browser.isForwardEnabled());
        backAction.setEnabled(browser.isBackEnabled());
    }

    /**
     * navigateBackward
     * 
     * @return boolean
     */
    public boolean navigateBackward() {
        return browser.back();
    }

    /**
     * navigateForward
     * 
     * @return boolean
     */
    public boolean navigateForward() {
        return browser.forward();
    }

    /**
     * navigateHome
     * 
     * @return boolean
     */
    public boolean navigateHome() {
        String location = url;
        boolean success = browser.setUrl(location);
        updateHistory(location);

        return success;
    }

    /**
     * Updates the UI navigation history with either a real URL.
     * 
     * @param location
     */
    public void updateHistory(String location) {
        history.updateHistory(location);
        updateNavigationActionsState();
    }

    /**
     * Retrieves the image descriptor associated with resource from the image
     * descriptor registry. If the image descriptor cannot be retrieved, attempt
     * to find and load the image descriptor at the location specified in
     * resource.
     * 
     * @param imageFilePath
     *            the image descriptor to retrieve
     * @return The image descriptor assocated with resource or the default
     *         "missing" image descriptor if one could not be found
     */
    private static ImageDescriptor getImageDescriptor(String imageFilePath) {

        ImageDescriptor imageDescriptor = AbstractUIPlugin.imageDescriptorFromPlugin("org.eclipse.eclipsemonkey.ui", //$NON-NLS-1$
                imageFilePath);

        if (imageDescriptor == null) {
            imageDescriptor = ImageDescriptor.getMissingImageDescriptor();
        }

        return imageDescriptor;
    }

    /**
     * A Location Listener that knows how to intercept OOBE action URLs. It also knows how to update UI navigation
     * history.
     */
    private class BrowserIntroPartLocationListener implements LocationListener {
        private BrowserView implementation;

        /**
         * Takes the implementation as an input.
         * 
         * @param implementation
         */
        public BrowserIntroPartLocationListener(BrowserView implementation) {
            this.implementation = implementation;
        }

        /**
         * @see org.eclipse.swt.browser.LocationListener#changed(org.eclipse.swt.browser.LocationEvent)
         */
        public void changed(LocationEvent event) {
            String url = event.location;
            if (url == null) {
                return;
            }

            // guard against unnecessary History updates.
            Browser browser = (Browser) event.getSource();
            if (browser.getData("navigation") != null //$NON-NLS-1$
                    && browser.getData("navigation").equals("true")) //$NON-NLS-1$ //$NON-NLS-2$
            {
                return;
            }
        }

        /**
         * Intercept any LocationEvents on the browser. If the event location is a valid IntroURL, cancel the event and
         * execute the intro action that is embedded in the URL
         * 
         * @param event
         */
        public void changing(LocationEvent event) {
            String url = event.location;
            if (url == null) {
                return;
            }
        }

        /**
         * flagStartOfFrameNavigation
         */
        public void flagStartOfFrameNavigation() {
            if (implementation.getBrowser().getData("frameNavigation") == null) //$NON-NLS-1$
            {
                implementation.getBrowser().setData("frameNavigation", "true"); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        /**
         * flagEndOfFrameNavigation
         */
        public void flagEndOfFrameNavigation() {
            implementation.getBrowser().setData("frameNavigation", null); //$NON-NLS-1$
        }

        /**
         * flagStartOfNavigation
         */
        public void flagStartOfNavigation() {
            if (implementation.getBrowser().getData("navigation") == null) //$NON-NLS-1$
            {
                implementation.getBrowser().setData("navigation", "true"); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        /**
         * flagEndOfNavigation
         */
        public void flagEndOfNavigation() {
            implementation.getBrowser().setData("navigation", null); //$NON-NLS-1$
        }

        /**
         * flagStoredTempUrl
         */
        public void flagStoredTempUrl() {
            if (implementation.getBrowser().getData("tempUrl") == null) //$NON-NLS-1$
            {
                implementation.getBrowser().setData("tempUrl", "true"); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }

        /**
         * flagRemovedTempUrl
         */
        public void flagRemovedTempUrl() {
            implementation.getBrowser().setData("tempUrl", null); //$NON-NLS-1$
        }
    }

    /**
     * All browser history
     * 
     * @author Ingo Muschenetz
     */
    private class History {
        // History of Intro Pages and real URL visited by Intro Browser. All
        // elements are all of type HistoryObject.
        private Vector history = new Vector();

        private int navigationLocation = 0;

        /**
         * Model class for history objects. A history object may be a URL or an Intro page. A URL is a regular URL
         * navigated to from a fully qualified link. An intro page may be an IFrame page. IFrame pages are not created
         * for every Help topic navigated in an embedded IFrame. Instead the same IFrame is stored in history as a
         * different object with the IFrameURL set. This way the model actually creates one page for every embedded Help
         * Topic target but the navigation history updates the IFrame accordingly.
         */
        class HistoryObject {
            String iframeUrl;

            String url;

            HistoryObject(Object location) {
                if (location instanceof String) {
                    this.url = (String) location;
                }
            }

            String getIFrameUrl() {
                return iframeUrl;
            }

            String getUrl() {
                return url;
            }

            boolean isURL() {
                return (url != null) ? true : false;
            }

            boolean isIFramePage() {
                return (iframeUrl != null) ? true : false;
            }

        }

        /**
         * Updates the UI navigation history with either a real URL, or a page ID.
         * 
         * @param location
         */
        public void updateHistory(String location) {
            // quick exit.
            if (!history.isEmpty() && isSameLocation(location)) {
                // resetting the same location is useless.
                return;
            }
            doUpdateHistory(location);
        }

        private void doUpdateHistory(Object location) {
            // we got here due to an intro URL listener or an SWT Form hyperlink
            // listener. location may be a URL or an IntroPage.
            if (navigationLocation == getHistoryEndPosition()) {
                // we are at the end of the vector, just push.
                pushToHistory(location);
            } else {
                // we already navigated. add item at current location, and clear
                // rest of history. (Same as browser behavior.)
                trimHistory(location);
            }
        }

        private boolean isSameLocation(Object location) {
            HistoryObject currentLocation = getCurrentLocation();
            if (location instanceof String && currentLocation.isURL()) {
                return currentLocation.getUrl().equals(location);
            }

            return false;
        }

        private void pushToHistory(Object location) {
            history.add(new HistoryObject(location));
            // point the nav location to the end of the vector.
            navigationLocation = getHistoryEndPosition();
        }

        /**
         * removeLastHistory
         */
        public void removeLastHistory() {
            history.remove(getHistoryEndPosition());
            // point the nav location to the end of the vector.
            navigationLocation = getHistoryEndPosition();
        }

        private void trimHistory(Object location) {
            List newHistory = history.subList(0, navigationLocation + 1);
            history = new Vector(newHistory);
            history.add(new HistoryObject(location));
            // point the nav location to the end of the vector.
            navigationLocation = getHistoryEndPosition();
        }

        /**
         * Return the position of the last element in the navigation history. If vector is empty, return 0.
         * 
         * @param vector
         * @return int
         */
        private int getHistoryEndPosition() {
            if (history.isEmpty()) {
                return 0;
            }
            return history.size() - 1;
        }

        /**
         * navigateHistoryBackward
         */
        public void navigateHistoryBackward() {
            if (badNavigationLocation(navigationLocation - 1)) {
                // do nothing. We are at the beginning.
                return;
            }
            --navigationLocation;
        }

        /**
         * Navigate forward in the history.
         */
        public void navigateHistoryForward() {
            if (badNavigationLocation(navigationLocation + 1)) {
                // do nothing. We are at the beginning.
                return;
            }
            ++navigationLocation;
        }

        private boolean badNavigationLocation(int navigationLocation) {
            if (navigationLocation < 0 || navigationLocation >= history.size()) {
                // bad nav location.
                return true;
            }
            return false;
        }

        /**
         * Returns true if the current location in the navigation history represents a URL. False if the location is an
         * Intro Page id.
         * 
         * @return Returns the locationIsURL.
         */
        private HistoryObject getCurrentLocation() {
            return (HistoryObject) history.elementAt(navigationLocation);
        }

        /**
         * canNavigateForward
         * 
         * @return boolean
         */
        public boolean canNavigateForward() {
            return navigationLocation != getHistoryEndPosition() ? true : false;
        }

        /**
         * canNavigateBackward
         * 
         * @return boolean
         */
        public boolean canNavigateBackward() {
            return navigationLocation == 0 ? false : true;
        }

        /**
         * currentLocationIsUrl
         * 
         * @return boolean
         */
        public boolean currentLocationIsUrl() {
            return getCurrentLocation().isURL();
        }

        /**
         * getCurrentLocationAsUrl
         * 
         * @return boolean
         */
        public String getCurrentLocationAsUrl() {
            return getCurrentLocation().getUrl();
        }

        /**
         * clear
         */
        public void clear() {
            history.clear();
            navigationLocation = 0;
        }

    }
}