/**
* Copyright (c) 2012 by JP Moresmau
* This code is made available under the terms of the Eclipse Public License,
* version 1.0 (EPL). See http://www.eclipse.org/legal/epl-v10.html
*/
package net.sf.eclipsefp.haskell.ui.internal.search;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import net.sf.eclipsefp.haskell.buildwrapper.usage.UsageQueryFlags;
import net.sf.eclipsefp.haskell.core.util.ResourceUtil;
import net.sf.eclipsefp.haskell.ui.internal.util.UITexts;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.search.ui.ISearchPage;
import org.eclipse.search.ui.ISearchPageContainer;
import org.eclipse.search.ui.ISearchResultViewPart;
import org.eclipse.search.ui.NewSearchUI;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.progress.UIJob;
/**
* The page presenting criteria for a Haskell search
* @author JP Moresmau
*
*/
public class HaskellSearchPage extends DialogPage implements ISearchPage{
/**
* previous search terms
*/
private static LinkedList<String> previous=new LinkedList<>();
/**
* previous type
*/
private static int previousType=UsageQueryFlags.TYPE_VAR;
/**
* previous scope
*/
private static int previousScope=UsageQueryFlags.SCOPE_ALL;
private ISearchPageContainer container;
/**
* list of terms
*/
private ComboViewer termList;
/**
* type buttons: buttons to type
*/
private final Map<Button,Integer> buttonsToType=new HashMap<>();
/**
* scope buttons: buttons to scope
*/
private final Map<Button,Integer> buttonsToScope=new HashMap<>();
public HaskellSearchPage() {
super();
}
public HaskellSearchPage( final String title, final ImageDescriptor image ) {
super( title, image );
}
public HaskellSearchPage( final String title ) {
super( title );
}
protected void updateStatus(){
container.setPerformActionEnabled( termList.getCombo().getText().trim().length()>0 );
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createControl( final Composite arg0 ) {
Composite main=new Composite(arg0,SWT.NONE);
main.setLayout( new GridLayout(2,false) );
Label l=new Label(main,SWT.NONE);
l.setText( UITexts.SearchPage_text );
GridData gd=new GridData( GridData.HORIZONTAL_ALIGN_FILL );
gd.horizontalSpan=2;
l.setLayoutData( gd );
termList=new ComboViewer( main,SWT.NONE );
gd=new GridData( GridData.HORIZONTAL_ALIGN_FILL );
gd.horizontalSpan=2;
termList.getCombo().setLayoutData( gd );
termList.setContentProvider( new ArrayContentProvider() );
termList.setInput( previous );
if (previous.size()>0){
termList.getCombo().select( 0 );
}
termList.getCombo().addModifyListener( new ModifyListener() {
@Override
public void modifyText( final ModifyEvent arg0 ) {
updateStatus();
}
} );
termList.addSelectionChangedListener( new ISelectionChangedListener() {
@Override
public void selectionChanged( final SelectionChangedEvent arg0 ) {
updateStatus();
}
} );
Group gType=new Group(main,SWT.NONE);
gType.setText( UITexts.SearchPage_type );
gType.setLayout( new GridLayout(2,true) );
final Button bModule=createTypeButton(gType,UsageQueryFlags.TYPE_MODULE,UITexts.SearchPage_type_modules);
createTypeButton(gType,UsageQueryFlags.TYPE_TYPE,UITexts.SearchPage_type_types);
createTypeButton(gType,UsageQueryFlags.TYPE_CONSTRUCTOR,UITexts.SearchPage_type_constructors);
final Button bFunctions=createTypeButton(gType,UsageQueryFlags.TYPE_VAR,UITexts.SearchPage_type_functions);
Group gScope=new Group(main,SWT.NONE);
gScope.setText( UITexts.SearchPage_scope );
gScope.setLayout( new GridLayout(2,true) );
final Button bAll=createScopeButton( gScope, UsageQueryFlags.SCOPE_ALL, UITexts.SearchPage_scope_all );
createScopeButton( gScope, UsageQueryFlags.SCOPE_DEFINITIONS, UITexts.SearchPage_scope_declarations );
final Button bRefs=createScopeButton( gScope, UsageQueryFlags.SCOPE_REFERENCES, UITexts.SearchPage_scope_references );
setControl( main );
// preselect module if we have a file
if (container.getSelection() instanceof IStructuredSelection){
Object o=((IStructuredSelection)container.getSelection()).getFirstElement();
if (o instanceof IFile){
String module=ResourceUtil.getModuleName( (IFile )o);
if (module!=null && module.length()>0){
termList.getCombo().setText( module );
bModule.setSelection( true );
bFunctions.setSelection( false );
bModule.notifyListeners( SWT.Selection, new Event() );
bRefs.setSelection( true );
bAll.setSelection( false );
bRefs.notifyListeners( SWT.Selection, new Event() );
}
}
}
updateStatus();
setErrorMessage( null );
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)
*/
@Override
public void setVisible( final boolean visible ) {
if (visible){
updateStatus();
IEditorInput editorInput =container.getActiveEditorInput();
container.setActiveEditorCanProvideScopeSelection((editorInput != null) && (editorInput.getAdapter(IFile.class) != null));
}
super.setVisible( visible );
if (visible){
termList.getCombo().setFocus();
}
}
private Button createTypeButton(final Group gType,final int type,final String text){
Button b=new Button(gType,SWT.RADIO);
b.setText( text );
buttonsToType.put( b, type );
b.setSelection( type == previousType );
return b;
}
private Button createScopeButton(final Group gScope,final int type,final String text){
Button b=new Button(gScope,SWT.RADIO);
b.setText( text );
buttonsToScope.put( b, type );
b.setSelection( type == previousScope);
return b;
}
/* (non-Javadoc)
* @see org.eclipse.search.ui.ISearchPage#performAction()
*/
@Override
public boolean performAction() {
String term=termList.getCombo().getText();
if (term.length()>0){
previous.remove( term );
previous.addFirst( term );
String[] projects=container.getSelectedProjectNames();
IWorkingSet[] sets=container.getSelectedWorkingSets();
// get all projects referenced in scope
Set<IProject> projs=new HashSet<>();
// other resources to filter with
Set<IResource> otherResources=new HashSet<>();
// projects selected
if (projects!=null){
IWorkspaceRoot root=ResourcesPlugin.getWorkspace().getRoot();
for (String pn:projects){
IProject p=root.getProject( pn );
if (p!=null){
projs.add(p);
}
}
// working sets
} else if (sets!=null) {
for (IWorkingSet set:sets){
for (IAdaptable adp:set.getElements()){
if (adp instanceof IProject){
projs.add(( IProject )adp);
} else if (adp instanceof IResource){
otherResources.add( (IResource )adp);
} else {
Object o=adp.getAdapter( IResource.class );
if (o instanceof IProject){
projs.add(( IProject )o);
} else if (o instanceof IResource){
otherResources.add( (IResource )o);
}
}
}
}
} else if (container.getSelectedScope()==ISearchPageContainer.SELECTION_SCOPE){
ISelection sel=container.getSelection();
// selection
if (sel instanceof IStructuredSelection && (!(sel.isEmpty()))){
for (Iterator<?> it=((IStructuredSelection)sel).iterator();it.hasNext();){
Object o=it.next();
if (o instanceof IProject){
projs.add(( IProject )o);
} else if (o instanceof IResource){
otherResources.add( (IResource )o);
}
}
// editor
} else if (container.getActiveEditorInput()!=null){
Object o=container.getActiveEditorInput().getAdapter(IFile.class);
if (o instanceof IResource){
otherResources.add((IResource) o);
}
}
}
// get flags from checked buttons
final UsageQuery uq=new UsageQuery( term, projs );
uq.setExact( false );
for (Map.Entry<Button,Integer> me:buttonsToType.entrySet()){
if (me.getKey().getSelection()){
uq.setTypeFlags( me.getValue() );
}
}
for (Map.Entry<Button,Integer> me:buttonsToScope.entrySet()){
if (me.getKey().getSelection()){
uq.setScopeFlags( me.getValue() );
}
}
previousScope=uq.getScopeFlags();
previousType=uq.getTypeFlags();
if (otherResources.size()>0){
uq.setRestrictedResources( otherResources );
}
new UIJob( UITexts.openDefinition_select_job ) {
@Override
public IStatus runInUIThread( final IProgressMonitor monitor ) {
final ISearchResultViewPart p=NewSearchUI.activateSearchResultView();
NewSearchUI.runQueryInBackground( uq,p);
return Status.OK_STATUS;
}
}.schedule();
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.search.ui.ISearchPage#setContainer(org.eclipse.search.ui.ISearchPageContainer)
*/
@Override
public void setContainer( final ISearchPageContainer paramISearchPageContainer ) {
this.container=paramISearchPageContainer;
//this.container.setActiveEditorCanProvideScopeSelection( this.container.getActiveEditorInput() instanceof FileEditorInput );
//this.container.setActiveEditorCanProvideScopeSelection(false);
}
}