Package org.locationtech.udig.catalog.ui.search

Source Code of org.locationtech.udig.catalog.ui.search.ResourceSearchComposite$SearchJob

/*
*    uDig - User Friendly Desktop Internet GIS client
*    http://udig.refractions.net
*    (C) 2012 Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*
*/
package org.locationtech.udig.catalog.ui.search;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.locationtech.udig.catalog.CatalogPlugin;
import org.locationtech.udig.catalog.IResolve;
import org.locationtech.udig.catalog.ISearch;
import org.locationtech.udig.catalog.ui.CatalogUIPlugin;
import org.locationtech.udig.catalog.ui.ResolveContentProvider;
import org.locationtech.udig.catalog.ui.ResolveLabelProviderSimple;
import org.locationtech.udig.catalog.ui.ResolveTitlesDecorator;
import org.locationtech.udig.ui.PlatformGIS;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.geotools.data.FeatureSource;
import org.geotools.geometry.jts.ReferencedEnvelope;

/**
* Composite used to provide list of resource to be searched.
* <p>
* Intended for use in the AddLayer wizard, but packaged as a reusable composite.
* <p>
* When embedding this composite are interaction is provided using the ISelectionProvider
* interface. Since the primary selection of interest is a GeoResource a helper method
* has been provided for easy retrieval.
*
* @author Levi Putna
*/
public class ResourceSearchComposite extends Composite implements ISelectionProvider {
    private Text text;
    private List<ISearch> catalogs;
    private TreeViewer treeViewer;
    private static final long DELAY = 500;

    /**
     * Listen for key press and issue a search.
     * <p>
     * For most keys a small delay is used (to allow the user to type more); for return a
     * search is issued immediately.
     */
    private KeyAdapter keyListener = new KeyAdapter() {
        @Override
        public void keyReleased(KeyEvent e) {
            doSearch(DELAY); // search in a bit (incase they keep typing)
        }
    };
    private SelectionListener selectionListener = new SelectionAdapter() {
        @Override
        public void widgetDefaultSelected(SelectionEvent e) {
            doSearch(0); // search now!
        }
    };

    // Single job used for searching in the background
    SearchJob search = new SearchJob();

   
    /**
     * Creates a searchable catalog resource viewer.
     *
     * @param parent the parent that this composite will be added to
     * @param style the stile used on this composite {@see SWT}
     */
    public ResourceSearchComposite(Composite parent, int style) {
        super(parent, style);
        setLayout(new GridLayout(1, false));
   
        Label hintLabel = new Label(this, SWT.NONE);
        hintLabel.setText("Start typing in search term");
   
        text = new Text(this, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH );
        text.addKeyListener(keyListener);
        text.addSelectionListener( selectionListener );
   
        text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
   
        // Using SWT.SINGLE until we have "join" functionality
        treeViewer = new TreeViewer(this, SWT.BORDER | SWT.MULTI ); //  SWT.CHECK ?
       
        Tree tree = treeViewer.getTree();
   
        tree.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
   
        treeViewer.setContentProvider(createContentProvider());
        treeViewer.setLabelProvider(createLabelProvider());
       
        catalogs = Arrays.asList(CatalogPlugin.getDefault().getCatalogs());
    }

    public Control getControl(){
        return treeViewer != null ? treeViewer.getControl() : null;
    }

    public IStructuredSelection getSelection() {
        return (IStructuredSelection) treeViewer.getSelection();
    }

    @Override
    public void setSelection(ISelection selection) {
        treeViewer.setSelection( selection );
    }

    /**
     * Adds a listener for selection changes in this selection provider. Has no effect if an
     * identical listener is already registered.
     *
     * @param listener the listener to add
     */
    @Override
    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        treeViewer.addSelectionChangedListener(listener);
    }
    /**
     * Removes the given selection change listener from this selection provider. Has no effect if an
     * identical listener is not registered.
     *
     * @param listener the listener to remove
     */
    @Override
    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        treeViewer.removeSelectionChangedListener(listener);
    }

    public void setSearchText( final String search ){
        PlatformGIS.asyncInDisplayThread(
        new Runnable() {
           
            @Override
            public void run() {
                if( text != null && !text.isDisposed() ){
                    text.setText( search != null ? search : "" );
                    doSearch( 0 );               
                }
            }
        },true );
    }
    public String getSearchText(){
        if( text != null && !text.isDisposed() ){
            return text.getText();
        }
        return null;
    }
   
    /**
     * LabelProvider; override to take charge of your labels and icons.
     *
     * @return LabelProvider for use with the viewer
     */
    protected IBaseLabelProvider createLabelProvider() {
        ResolveLabelProviderSimple base = new ResolveLabelProviderSimple();
        return new DecoratingLabelProvider(base, new ResolveTitlesDecorator(base));
    }
   
    /**
     * Default implementation will work for lists, please overide if you are into the whole tree
     * thing.
     *
     * @return
     */
    protected IStructuredContentProvider createContentProvider() {
        return new ResolveContentProvider();
    }

    /**
     * Search the catalogs for the input text and create tree items for results. This is ran in a
     * background thread and will need to call {@link #doSearchCallback(List)} to update UI with
     * search results.
     * @param delay a time delay in milliseconds before the search should run
     */
    protected void doSearch(long delay) {
        if( search.getState() == Job.RUNNING ){
            search.cancel();
        }
        String searchText = text.getText();
        if( !searchText.isEmpty() ){
            search.setSearchText( searchText );
            search.schedule( delay );
        }
        else {
            List<IResolve> empty = new ArrayList<IResolve>();
            doSearchCallback( empty );
        }
    }
   
    /**
     * {@link #doSearch()} callback to update the UI.
     *
     * @param resolves
     */
    protected void doSearchCallback(final List<IResolve> resolves) {
        reviewResults( resolves );
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                treeViewer.setInput(resolves);
            }
        });
    }
    protected void reviewResults(List<IResolve> resolves) {
        // do nothing
    }
    /**
     * Search catalogs in a separate job.
     *
     * @author Jody Garnett
     */
    class SearchJob extends Job {
       
        private String searchText;
        private ReferencedEnvelope bounds = new ReferencedEnvelope();
       
        public SearchJob(){
            super("Search Catalog"); //$NON-NLS-1$
        }
       
        public String getSearchText() {
            return searchText;
        }

        public void setSearchText(String searchText) {
            this.searchText = searchText;
        }

        public ReferencedEnvelope getBounds() {
            return bounds;
        }

        public void setBounds(ReferencedEnvelope bounds) {
            this.bounds = bounds;
        }

        @Override
        protected IStatus run( IProgressMonitor monitor ) {
            if( monitor == null ) monitor = new NullProgressMonitor();
           
            try {
                monitor.beginTask( "Seaching for "+searchText, catalogs.size()*100 );
                final List<IResolve> resolves = new CopyOnWriteArrayList<IResolve>();
                for (ISearch search : catalogs) {
                    try {
                        monitor.subTask("Search "+search.getTitle() +" for "+searchText );
                        List<IResolve> searchResults = search.search(searchText, bounds, null);
                        monitor.worked(10);
                        IProgressMonitor searchMonitor = new SubProgressMonitor( monitor,10, SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK );
                       
                        for (IResolve member : searchResults) {
                            if (member.canResolve(FeatureSource.class)) {
                                resolves.add(member);
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                doSearchCallback(resolves);
                return Status.OK_STATUS;
            } catch (Exception e) {
                String message = "Unable to complete search for '"+searchText+"':"+e;
                Status failure = new Status( IStatus.ERROR, CatalogUIPlugin.ID, message, e );
                return failure;
            } finally {
                monitor.done();
            }
        }
    }
   
}
TOP

Related Classes of org.locationtech.udig.catalog.ui.search.ResourceSearchComposite$SearchJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.