au.gov.ga.earthsci.application.parts.browser.BrowserPart.java Source code

Java tutorial

Introduction

Here is the source code for au.gov.ga.earthsci.application.parts.browser.BrowserPart.java

Source

/*******************************************************************************
 * Copyright 2013 Geoscience Australia
 * 
 * Licensed 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 au.gov.ga.earthsci.application.parts.browser;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.eclipse.e4.ui.workbench.modeling.EPartService.PartState;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.OpenWindowListener;
import org.eclipse.swt.browser.WindowEvent;
import org.eclipse.swt.widgets.Composite;

import au.gov.ga.earthsci.application.intent.HtmlIntentHandler;
import au.gov.ga.earthsci.application.intent.HttpIntentHandler;
import au.gov.ga.earthsci.eclipse.extras.browser.BrowserViewer;
import au.gov.ga.earthsci.intent.AbstractIntentCallback;
import au.gov.ga.earthsci.intent.IIntentCallback;
import au.gov.ga.earthsci.intent.IIntentFilterSelectionPolicy;
import au.gov.ga.earthsci.intent.Intent;
import au.gov.ga.earthsci.intent.IntentFilter;
import au.gov.ga.earthsci.intent.IntentManager;
import au.gov.ga.earthsci.intent.dispatch.Dispatcher;

/**
 * Displays a web browser.
 * 
 * @author Michael de Hoog (michael.dehoog@ga.gov.au)
 */
public class BrowserPart {
    public static final String PART_ID = "au.gov.ga.earthsci.application.browser.part"; //$NON-NLS-1$
    public static final String INPUT_NAME = PART_ID + ".input"; //$NON-NLS-1$
    public static final String PERSISTED_URL_KEY = PART_ID + ".persistedUrl"; //$NON-NLS-1$

    @Inject
    private IEclipseContext context;

    private BrowserViewer viewer;

    @Inject
    private EPartService partService;

    @Inject
    private EModelService modelService;

    @Inject
    private MWindow window;

    @Inject
    private MPart part;

    private boolean dontStartIntent = false;

    @PostConstruct
    public void init(final Composite parent) {
        context.set(BrowserPart.class, this);

        viewer = new BrowserViewer(parent,
                BrowserViewer.BUTTON_BAR | BrowserViewer.LOCATION_BAR | BrowserViewer.DISABLE_NEW_WINDOW);
        viewer.getBrowser().addLocationListener(new LocationAdapter() {
            @Override
            public void changing(LocationEvent event) {
                if (!dontStartIntent) {
                    startIntent(parent, event.location);
                }
                dontStartIntent = false;
                part.getPersistedState().put(PERSISTED_URL_KEY, event.location);
            }
        });
        viewer.getBrowser().addOpenWindowListener(new OpenWindowListener() {
            @Override
            public void open(WindowEvent event) {
                MPart part = BrowserPart.showPart(partService, modelService, window, true);
                Object object = part.getObject();
                if (object instanceof BrowserPart) {
                    BrowserPart browserPart = (BrowserPart) object;
                    event.browser = browserPart.viewer.getBrowser();
                } else {
                    partService.hidePart(part, true);
                }
            }
        });

        String persistedUrl = part.getPersistedState().get(PERSISTED_URL_KEY);
        if (persistedUrl != null) {
            try {
                dontStartIntent = true;
                URL url = new URL(persistedUrl);
                setPartInput(url);
            } catch (MalformedURLException e) {
            }
        }
    }

    @PreDestroy
    public void dispose() {
        context.remove(BrowserPart.class);
    }

    protected void startIntent(final Composite parent, String location) {
        //Raise an "optional" intent for event.location. For example, if it is a WMS
        //capabilities document, the user can optionally open it as a catalog or layer.
        URI uri;
        try {
            uri = new URI(location);
        } catch (URISyntaxException e) {
            return;
        }
        Intent intent = new Intent();
        intent.setURI(uri);
        IIntentFilterSelectionPolicy filterSelectionPolicy = new IIntentFilterSelectionPolicy() {
            @Override
            public boolean allowed(Intent intent, IntentFilter filter) {
                //don't allow the filter to be the one that opens in the browser, causing a looping intent
                return !(HtmlIntentHandler.class.equals(filter.getHandler())
                        || HttpIntentHandler.class.equals(filter.getHandler()));
            }
        };
        IIntentCallback callback = new AbstractIntentCallback() {
            @Override
            public boolean filters(List<IntentFilter> filters, Intent intent) {
                if (filters.isEmpty()) {
                    return false;
                }
                final boolean[] result = new boolean[1];
                if (!parent.isDisposed()) {
                    parent.getDisplay().syncExec(new Runnable() {
                        @Override
                        public void run() {
                            result[0] = MessageDialog.openQuestion(parent.getShell(), "Open URL",
                                    "This URL can be handled by EarthSci. Would you like to continue?");
                        }
                    });
                }
                return result[0];
            }

            @Override
            public void error(Exception e, Intent intent) {
            }

            @Override
            public void completed(Object result, Intent intent) {
                if (result != null) {
                    Dispatcher.getInstance().dispatch(result, intent, context);
                }
            }
        };
        IntentManager.getInstance().start(intent, filterSelectionPolicy, false, callback, context);
    }

    public String getURL() {
        return viewer.getURL();
    }

    @Inject
    @Optional
    private void setPartInput(@Named(INPUT_NAME) URL url) {
        viewer.setURL(url.toString());
    }

    public static MPart showPart(EPartService partService, EModelService modelService, MWindow window,
            boolean newPart) {
        MPart part = null;

        if (!newPart) {
            List<MPart> reuse = modelService.findElements(window, PART_ID, MPart.class, null);
            if (!reuse.isEmpty()) {
                part = reuse.get(reuse.size() - 1);
            }
        }

        if (part == null) {
            //create the part from the PartDescriptor
            part = partService.createPart(PART_ID);

            //if there's a placeholder for the part, put it there
            List<MPlaceholder> placeholders = modelService.findElements(window, PART_ID, MPlaceholder.class, null);
            if (!placeholders.isEmpty()) {
                MPlaceholder placeholder = placeholders.get(0);
                List<MUIElement> siblings = placeholder.getParent().getChildren();
                int index = siblings.indexOf(placeholder);
                siblings.add(index, part);
            }
        }

        //show and return the part
        return partService.showPart(part, PartState.ACTIVATE);
    }
}