au.gov.ga.earthsci.discovery.ui.DiscoveryPart.java Source code

Java tutorial

Introduction

Here is the source code for au.gov.ga.earthsci.discovery.ui.DiscoveryPart.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.discovery.ui;

import gov.nasa.worldwind.SceneController;
import gov.nasa.worldwind.View;
import gov.nasa.worldwind.WorldWindow;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.view.orbit.OrbitView;

import java.util.ArrayList;
import java.util.List;

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

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;

import au.gov.ga.earthsci.application.Activator;
import au.gov.ga.earthsci.application.parts.globe.GlobeSceneController;
import au.gov.ga.earthsci.common.ui.dialogs.StackTraceDialog;
import au.gov.ga.earthsci.common.ui.information.IInformationProvider;
import au.gov.ga.earthsci.common.ui.information.InformationProviderHoverInformationControlManager;
import au.gov.ga.earthsci.common.ui.widgets.PageLinks;
import au.gov.ga.earthsci.common.ui.widgets.PageListener;
import au.gov.ga.earthsci.discovery.DiscoveryParameters;
import au.gov.ga.earthsci.discovery.DiscoveryServiceManager;
import au.gov.ga.earthsci.discovery.IDiscovery;
import au.gov.ga.earthsci.discovery.IDiscoveryListener;
import au.gov.ga.earthsci.discovery.IDiscoveryResult;
import au.gov.ga.earthsci.discovery.IDiscoveryResultHandler;
import au.gov.ga.earthsci.discovery.IDiscoveryResultLabelProvider;
import au.gov.ga.earthsci.discovery.IDiscoveryService;
import au.gov.ga.earthsci.discovery.ui.handler.ServicesHandler;
import au.gov.ga.earthsci.discovery.ui.handler.ViewOnGlobeHandler;
import au.gov.ga.earthsci.worldwind.common.WorldWindowRegistry;
import au.gov.ga.earthsci.worldwind.common.layers.Bounds;
import au.gov.ga.earthsci.worldwind.common.retrieve.SectorPolyline;
import au.gov.ga.earthsci.worldwind.common.view.orbit.FlyToOrbitViewAnimator;
import au.gov.ga.earthsci.worldwind.common.view.orbit.FlyToSectorAnimator;

/**
 * The Discovery UI part.
 * 
 * @author Michael de Hoog (michael.dehoog@ga.gov.au)
 */
public class DiscoveryPart implements IDiscoveryListener, PageListener {
    @Inject
    @Optional
    @Named(IServiceConstants.ACTIVE_SHELL)
    private Shell shell;

    @Inject
    private IEclipseContext context;

    @Inject
    private ESelectionService selectionService;

    @Inject
    private IEventBroker eventBroker;

    private Text searchText;
    private Button searchButton;
    private SashForm resultsSashForm;

    private TableViewer discoveriesViewer;
    private Composite resultsComposite;
    private Composite resultsViewerComposite;
    private TableViewer resultsViewer;
    private PageLinks pageLinks;

    private final List<IDiscovery> currentDiscoveries = new ArrayList<IDiscovery>();
    private final DiscoveryResultContentProvider discoveryContentProvider = new DiscoveryResultContentProvider();

    private IDiscoveryResult lastResultMouseOver;
    private RenderableLayer mouseOverLayer;
    private GlobeSceneController mouseOverSceneController;

    private IDiscoveryResult selectedResult;
    private boolean viewOnGlobe;

    @PostConstruct
    public void init(final Composite parent, final MPart part) {
        context.set(DiscoveryPart.class, this);
        viewOnGlobe = ViewOnGlobeHandler.isViewOnGlobe(part);

        parent.setLayout(new GridLayout(1, true));

        Composite searchComposite = new Composite(parent, SWT.NONE);
        searchComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        searchComposite.setLayout(createGridLayout(2, 0));

        searchText = new Text(searchComposite, SWT.SEARCH);
        searchText.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false));
        searchText.setMessage(Messages.DiscoveryPart_SearchPlaceholder);
        searchText.addTraverseListener(new TraverseListener() {
            @Override
            public void keyTraversed(TraverseEvent e) {
                if (e.detail == SWT.TRAVERSE_RETURN) {
                    performSearch();
                }
            }
        });

        searchButton = new Button(searchComposite, SWT.PUSH);
        searchButton.setLayoutData(new GridData(GridData.END, GridData.CENTER, false, false));
        searchButton.setText(Messages.DiscoveryPart_Search);
        searchButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                performSearch();
            }
        });
        searchText.addModifyListener(new ModifyListener() {
            @Override
            public void modifyText(ModifyEvent e) {
                searchButton.setEnabled(searchText.getText().length() != 0);
            }
        });
        searchButton.setEnabled(false);

        Composite resultsRootComposite = new Composite(parent, SWT.NONE);
        resultsRootComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        resultsRootComposite.setLayout(createGridLayout(1, 0));

        resultsSashForm = new SashForm(resultsRootComposite, SWT.VERTICAL | SWT.SMOOTH);
        resultsSashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

        discoveriesViewer = new TableViewer(resultsSashForm, SWT.BORDER);
        discoveriesViewer.setContentProvider(new ArrayContentProvider());
        discoveriesViewer.setLabelProvider(new DiscoveryLabelProvider());
        discoveriesViewer.setComparator(new DiscoveryComparator());

        resultsComposite = new Composite(resultsSashForm, SWT.NONE);
        resultsComposite.setLayout(createGridLayout(1, 0));

        resultsViewerComposite = new Composite(resultsComposite, SWT.NONE);
        resultsViewerComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
        resultsViewerComposite.setLayout(new FillLayout());

        createResultsViewer();

        pageLinks = new PageLinks(resultsComposite, SWT.NONE);
        pageLinks.setPageCount(20);
        pageLinks.setSelectedPage(4);
        pageLinks.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
        pageLinks.addPageListener(this);
        pageLinks.setVisible(false);
        ((GridData) pageLinks.getLayoutData()).exclude = true;

        resultsSashForm.setWeights(new int[] { 2, 8 });

        new TableViewerSelectionHelper<IDiscovery>(discoveriesViewer, IDiscovery.class) {
            @Override
            protected void itemSelected(IDiscovery selection) {
                discoverySelected(selection);
            }

            @Override
            protected void itemDefaultSelected(IDiscovery selection) {
                discoveryDefaultSelected(selection);
            }
        };
    }

    @PreDestroy
    public void dispose() {
        displaySectorAndZoom(null, false);
    }

    @Focus
    private void setFocus() {
        searchText.setFocus();
    }

    public void setViewOnGlobe(boolean viewOnGlobe) {
        this.viewOnGlobe = viewOnGlobe;
        resultSelected(selectedResult);
    }

    private void performSearch() {
        for (IDiscovery discovery : currentDiscoveries) {
            discovery.cancel();
        }
        currentDiscoveries.clear();
        discoverySelected(null);

        if (searchText.getText().length() > 0) {
            for (IDiscoveryService service : DiscoveryServiceManager.getServices()) {
                if (service.isEnabled()) {
                    DiscoveryParameters parameters = new DiscoveryParameters();
                    parameters.setQuery(searchText.getText());
                    IDiscovery discovery = service.createDiscovery(parameters);
                    if (discovery != null) {
                        currentDiscoveries.add(discovery);
                        discovery.addListener(DiscoveryPart.this);
                        discovery.start();
                    }
                }
            }

            if (currentDiscoveries.isEmpty()) {
                if (MessageDialog.openQuestion(shell, Messages.DiscoveryPart_NoServicesDialogTitle,
                        Messages.DiscoveryPart_NoServicesDialogMessage)) {
                    new ServicesHandler().execute(shell);
                }
            }
        }

        discoveriesViewer.setInput(currentDiscoveries);
        resultSelected(null);

        eventBroker.send(UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC, UIEvents.ALL_ELEMENT_ID);
    }

    public boolean canClearResults() {
        return searchText.getText().length() > 0 || !currentDiscoveries.isEmpty();
    }

    public void clearResults() {
        searchText.setText(""); //$NON-NLS-1$
        performSearch();
    }

    private void createResultsViewer() {
        if (resultsViewer != null) {
            resultsViewer.getControl().dispose();
        }

        resultsViewer = new TableViewer(resultsViewerComposite, SWT.BORDER | SWT.FULL_SELECTION);
        resultsViewer.setContentProvider(discoveryContentProvider);
        resultsViewer.getTable().setLinesVisible(true);
        resultsViewerComposite.layout();

        //keep the column width in sync with the table width
        final TableColumn resultsColumn = new TableColumn(resultsViewer.getTable(), SWT.LEFT);
        Listener resizeListener = new Listener() {
            @Override
            public void handleEvent(Event event) {
                resultsColumn.setWidth(resultsViewer.getTable().getClientArea().width);
            }
        };
        resultsViewer.getControl().addListener(SWT.Resize, resizeListener);
        resultsViewer.getControl().addListener(SWT.Paint, resizeListener);

        new TableViewerSelectionHelper<IDiscoveryResult>(resultsViewer, IDiscoveryResult.class) {
            @Override
            protected void itemSelected(IDiscoveryResult selection) {
                resultSelected(selection);
            }

            @Override
            protected void itemDefaultSelected(IDiscoveryResult selection) {
                resultDefaultSelected(selection);
            }
        };

        resultsViewer.getTable().addMouseMoveListener(new MouseMoveListener() {
            @Override
            public void mouseMove(MouseEvent e) {
                IDiscoveryResult result = null;
                ViewerCell cell = resultsViewer.getCell(new Point(e.x, e.y));
                if (cell != null) {
                    result = (IDiscoveryResult) cell.getElement();
                }
                resultMouseOver(result);
            }
        });
        resultsViewer.getTable().addMouseTrackListener(new MouseTrackAdapter() {
            @Override
            public void mouseExit(MouseEvent e) {
                resultMouseOver(null);
            }
        });
    }

    private void discoverySelected(IDiscovery discovery) {
        createResultsViewer();

        boolean pageLinksVisible = false;
        if (discovery != null) {
            pageLinksVisible = discovery.getPageSize() != 0;
            if (pageLinksVisible) {
                int resultCount = discovery.getResultCount();
                if (resultCount == IDiscovery.UNKNOWN) {
                    pageLinks.setPageCount(PageLinks.UNKNOWN_PAGE_COUNT);
                } else {
                    int pageCount = ((resultCount - 1) / discovery.getPageSize()) + 1;
                    pageLinks.setPageCount(pageCount);
                }
                pageLinks.setSelectedPage(0);
                pageChanged(0);
            }

            IDiscoveryResultLabelProvider labelProvider = discovery.getLabelProvider();
            resultsViewer.setLabelProvider(new DiscoveryResultLabelProvider(labelProvider));

            //enable focusable tooltips
            IInformationProvider provider = new DiscoveryResultInformationProvider(resultsViewer, labelProvider);
            IInformationControlCreator creator = new DiscoveryResultInformationControlCreator();
            InformationProviderHoverInformationControlManager.install(resultsViewer.getControl(), provider,
                    creator);
        }
        pageLinks.setVisible(pageLinksVisible);
        ((GridData) pageLinks.getLayoutData()).exclude = !pageLinksVisible;
        resultsComposite.layout();

        resultsViewer.setInput(discovery);
    }

    private void discoveryDefaultSelected(IDiscovery discovery) {
        if (discovery.getError() != null) {
            Throwable e = discovery.getError();
            IStatus status = new Status(IStatus.ERROR, Activator.getBundleName(), e.getLocalizedMessage(), e);
            StackTraceDialog.openError(shell, Messages.DiscoveryPart_Error, null, status);
        }
    }

    private static GridLayout createGridLayout(int numColumns, int margins) {
        GridLayout layout = new GridLayout(numColumns, false);
        layout.marginWidth = layout.marginHeight = margins;
        return layout;
    }

    @Override
    public void resultCountChanged(final IDiscovery discovery) {
        final ColumnViewer viewer = discoveriesViewer;
        if (!viewer.getControl().isDisposed()) {
            viewer.getControl().getDisplay().asyncExec(new Runnable() {
                @Override
                public void run() {
                    if (!viewer.getControl().isDisposed()) {
                        viewer.refresh(discovery);
                    }
                }
            });
        }
    }

    @Override
    public void resultAdded(IDiscovery discovery, IDiscoveryResult result) {
    }

    @Override
    public void pageChanged(int page) {
        discoveryContentProvider.setPage(page);
    }

    private void resultSelected(IDiscoveryResult result) {
        this.selectedResult = result;
        selectionService.setSelection(result);
        displaySectorAndZoom(viewOnGlobe ? result : null, true);
    }

    private void resultDefaultSelected(IDiscoveryResult result) {
        IDiscoveryResultHandler handler = result.getDiscovery().getService().getProvider().getHandler();
        ContextInjectionFactory.inject(handler, context);
        handler.open(result);
    }

    private void resultMouseOver(IDiscoveryResult result) {
    }

    private void displaySectorAndZoom(IDiscoveryResult result, boolean zoom) {
        if (lastResultMouseOver != result) {
            lastResultMouseOver = result;

            if (mouseOverLayer == null) {
                mouseOverLayer = new RenderableLayer();
            }

            Bounds bounds = null;
            mouseOverLayer.removeAllRenderables();
            if (result != null) {
                bounds = result.getBounds();
                if (bounds != null) {
                    mouseOverLayer.addRenderable(new SectorPolyline(bounds.toSector()));
                }
            }

            WorldWindow wwd = WorldWindowRegistry.INSTANCE.getActive();
            if (wwd != null) {
                SceneController sceneController = wwd.getSceneController();
                if (bounds != null && sceneController instanceof GlobeSceneController) {
                    GlobeSceneController gsc = (GlobeSceneController) sceneController;
                    if (mouseOverSceneController != gsc) {
                        if (mouseOverSceneController != null) {
                            mouseOverSceneController.getPostLayers().remove(mouseOverLayer);
                        }
                        mouseOverSceneController = gsc;
                        mouseOverSceneController.getPostLayers().add(mouseOverLayer);
                    }
                } else if (mouseOverSceneController != null) {
                    mouseOverSceneController.getPostLayers().remove(mouseOverLayer);
                    mouseOverSceneController = null;
                }
                wwd.redraw();

                if (zoom) {
                    View view = WorldWindowRegistry.INSTANCE.getActiveView();
                    if (view instanceof OrbitView && bounds != null) {
                        OrbitView orbitView = (OrbitView) view;
                        Position center = orbitView.getCenterPosition();
                        Position newCenter;
                        if (bounds.contains(center) && bounds.deltaLatitude.degrees > 90
                                && bounds.deltaLongitude.degrees > 90) {
                            newCenter = center;
                        } else {
                            newCenter = bounds.center;
                        }

                        LatLon endVisibleDelta = new LatLon(bounds.deltaLatitude, bounds.deltaLongitude);
                        FlyToOrbitViewAnimator animator = FlyToSectorAnimator.createScaledFlyToSectorAnimator(
                                orbitView, center, newCenter, orbitView.getHeading(), orbitView.getPitch(),
                                orbitView.getZoom(), endVisibleDelta, 10);
                        orbitView.stopAnimations();
                        orbitView.stopMovement();
                        orbitView.addAnimator(animator);
                        orbitView.firePropertyChange(AVKey.VIEW, null, orbitView);
                    }
                }
            }
        }
    }
}