/*
* Copyright (c) 2009 Andrejs Jermakovics.
*
* 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
*
* Contributors:
* Andrejs Jermakovics - initial implementation
*/
package it.unibz.instasearch.ui;
import it.unibz.instasearch.indexing.SearchQuery;
import it.unibz.instasearch.indexing.SearchResultDoc;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.TreeItem;
/**
* A search job that runs search in UI thread.
* Is used to start search after user has stopped typing
*/
public class SearchJob extends Job {
/**
*
*/
private TreeViewer resultViewer = null;
private SearchQuery searchQuery = null;
private boolean selectLast = false;
private InstaSearchView searchView;
private IStatusLineManager statusLineManager;
public SearchJob(InstaSearchView searchView)
{
super("Search");
this.searchView = searchView;
this.resultViewer = searchView.getResultViewer();
this.statusLineManager = searchView.getViewSite().getActionBars().getStatusLineManager();
this.addJobChangeListener(new JobChangeAdapter(){
public void done(IJobChangeEvent event) {
if( event.getResult() == Status.CANCEL_STATUS )
cancelSearch();
}
});
setPriority(Job.INTERACTIVE);
}
public void schedule(SearchQuery searchQuery, boolean selectLast, long delay) {
cancelSearch();
this.searchQuery = searchQuery;
this.selectLast = selectLast;
if( this.searchQuery != null ) {
this.searchQuery.setCanceled(false);
this.searchQuery.setCurrentProject( InstaSearchUI.getActiveProject() );
schedule(delay);
}
}
/**
* Cancel current search
*/
private void cancelSearch() {
if( searchQuery != null )
searchQuery.setCanceled(true);
}
protected IStatus run(IProgressMonitor monitor)
{
ResultContentProvider prov = (ResultContentProvider) resultViewer.getContentProvider();
if( prov == null || monitor.isCanceled() || searchQuery == null || searchQuery.isCanceled() ) return Status.CANCEL_STATUS;
prov.getElements(searchQuery); // runs query and caches result. running in this job to avoid UI freeze
if( monitor.isCanceled() || searchQuery.isCanceled() ) return Status.CANCEL_STATUS; // perhaps we cancelled while executing query
Display display = resultViewer.getControl().getDisplay();
display.syncExec(new Runnable() {
public void run() {
search(); // run in UI
}
});
return Status.OK_STATUS;
}
private void search() {
int items = resultViewer.getTree().getItemCount();
resultViewer.setInput(searchQuery); // run in UI, displays cached results immediately
int newItems = resultViewer.getTree().getItemCount();
if( selectLast && items != 0 && newItems >= items )
resultViewer.getTree().setSelection(resultViewer.getTree().getItem(items-1)); // show previous selection
int resultCount = countSearchResults(newItems);
String resultsDesc = " " + (searchQuery.isExact() ? "exact" : "similar") + " results";
if( searchQuery.isLimited() ) // limited
{
if( resultCount >= searchQuery.getMaxResults() )
statusLineManager.setMessage(searchView.getTitleImage(), searchQuery.getMaxResults() + "+" + resultsDesc + " (Ctrl+Enter to see all)");
else
statusLineManager.setMessage(searchView.getTitleImage(), resultCount + resultsDesc);
}
else { // not limited
statusLineManager.setMessage(searchView.getTitleImage(), resultCount + resultsDesc);
}
}
/**
* @param newItems
* @return
*/
private int countSearchResults(int newItems) {
int i, allItems = resultViewer.getTree().getItemCount();
for(i = allItems-1; i >= 0; i--)
{
TreeItem treeItem = resultViewer.getTree().getItem(i);
if( treeItem == null || treeItem.getData() == null )
continue;
if( treeItem.getData() instanceof SearchResultDoc ) // from now on we have results
return i+1;
}
return 0;
}
}