package com.redhat.ceylon.eclipse.code.search; import static com.redhat.ceylon.eclipse.util.EditorUtil.getCurrentEditor; import static com.redhat.ceylon.eclipse.util.EditorUtil.getSelectionText; import static org.eclipse.search.ui.ISearchPageContainer.SELECTED_PROJECTS_SCOPE; import static org.eclipse.search.ui.ISearchPageContainer.SELECTION_SCOPE; import static org.eclipse.search.ui.ISearchPageContainer.WORKING_SET_SCOPE; import static org.eclipse.search.ui.ISearchPageContainer.WORKSPACE_SCOPE; import static org.eclipse.ui.dialogs.PreferencesUtil.createPreferenceDialogOn; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.search.ui.ISearchPage; import org.eclipse.search.ui.ISearchPageContainer; 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.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.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.editors.text.TextEditor; import com.redhat.ceylon.eclipse.code.preferences.CeylonFiltersPreferencePage; import com.redhat.ceylon.eclipse.code.preferences.CeylonOutlinesPreferencePage; import com.redhat.ceylon.eclipse.util.SearchVisitor; public class CeylonSearchDialogPage extends DialogPage implements ISearchPage { private static final IResource[] NO_RESOURCES = new IResource[0]; private String searchPattern; private static boolean caseSensitive = false; private static boolean regex = false; private static boolean declarations = true; private static boolean imports = true; private static boolean references = true; private static boolean types = true; private static boolean archives = true; private static boolean sources = true; private static boolean docs = true; private static int kinds = SearchVisitor.ANYTHING; private static ISearchPageContainer container; private static List<String> previousPatterns = new ArrayList<String>(); public CeylonSearchDialogPage() { super("Ceylon Search"); } @Override public void createControl(Composite parent) { initSearchPattern(); Composite control = new Composite(parent, SWT.NONE); control.setLayout(new GridLayout()); control.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, true, false)); setControl(control); Composite outer = new Composite(control, SWT.NONE); outer.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, true, false)); GridLayout layout = new GridLayout(); layout.numColumns = 3; outer.setLayout(layout); Composite result = new Composite(outer, SWT.NONE); result.setLayout(new GridLayout()); GridData mgd = new GridData( SWT.FILL, SWT.BEGINNING, true, false); mgd.horizontalSpan = 2; result.setLayoutData(mgd); Label title = new Label(result, SWT.RIGHT); title.setText("Search string (* = any string, ? = any character):"); final Combo text = new Combo(result, 0); text.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, true, false)); text.setText(searchPattern); text.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent event) { searchPattern = text.getText(); } }); for (String string: previousPatterns) { text.add(string); } Composite options = new Composite(outer, SWT.NONE); options.setLayout(new GridLayout()); options.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, false, false)); Button regExp = new Button(options, SWT.CHECK); regExp.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, false, false)); regExp.setText("Regular expression"); regExp.setSelection(regex); regExp.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { regex = !regex; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Button caseSense = new Button(options, SWT.CHECK); caseSense.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, false, false)); caseSense.setText("Case sensitive"); caseSense.setSelection(caseSensitive); caseSense.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { caseSensitive = !caseSensitive; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); outer = new Composite(control, SWT.NONE); outer.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, true, false)); layout = new GridLayout(); layout.numColumns = 3; outer.setLayout(layout); Group sub = new Group(outer, SWT.SHADOW_ETCHED_IN); sub.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, true, false)); sub.setText("Search For"); sub.setLayout(new GridLayout(2,false)); final Button ab = new Button(sub, SWT.CHECK); GridData bdg = new GridData(); bdg.horizontalSpan = 2; bdg.horizontalAlignment = SWT.FILL; bdg.grabExcessHorizontalSpace = true; ab.setLayoutData(bdg); ab.setText("Anything"); ab.setSelection(kinds==SearchVisitor.ANYTHING); final Button tb = new Button(sub, SWT.RADIO); tb.setText("Types"); tb.setSelection(kinds==SearchVisitor.TYPE); tb.setEnabled(kinds!=SearchVisitor.ANYTHING); final Button fb = new Button(sub, SWT.RADIO); fb.setText("Functions"); fb.setSelection(kinds==SearchVisitor.FUNCTION); fb.setEnabled(kinds!=SearchVisitor.ANYTHING); final Button vb = new Button(sub, SWT.RADIO); vb.setText("Values"); vb.setSelection(kinds==SearchVisitor.VALUE); vb.setEnabled(kinds!=SearchVisitor.ANYTHING); final Button pb = new Button(sub, SWT.RADIO); pb.setText("Packages"); pb.setSelection(kinds==SearchVisitor.PACKAGES); pb.setEnabled(kinds!=SearchVisitor.ANYTHING); ab.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (ab.getSelection()) { kinds = SearchVisitor.ANYTHING; tb.setEnabled(false); fb.setEnabled(false); vb.setEnabled(false); pb.setEnabled(false); tb.setSelection(false); fb.setSelection(false); vb.setSelection(false); pb.setSelection(false); } else { kinds = SearchVisitor.TYPE; tb.setEnabled(true); fb.setEnabled(true); vb.setEnabled(true); pb.setEnabled(true); tb.setSelection(true); fb.setSelection(false); vb.setSelection(false); pb.setSelection(false); } } }); tb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (tb.getSelection()) { kinds = SearchVisitor.TYPE; } } }); fb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (fb.getSelection()) { kinds = SearchVisitor.FUNCTION; } } }); vb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (vb.getSelection()) { kinds = SearchVisitor.VALUE; } } }); pb.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (pb.getSelection()) { kinds = SearchVisitor.PACKAGES; } } }); sub = new Group(outer, SWT.SHADOW_ETCHED_IN); sub.setLayoutData(new GridData( SWT.FILL, SWT.BEGINNING, true, false)); sub.setText("Limit To"); sub.setLayout(new GridLayout(2,false)); Button dec = new Button(sub, SWT.CHECK); dec.setText("Declarations"); dec.setSelection(declarations); dec.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { declarations = !declarations; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Button ref = new Button(sub, SWT.CHECK); ref.setText("Expressions"); ref.setSelection(references); ref.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { references = !references; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Button type = new Button(sub, SWT.CHECK); type.setText("Types"); type.setSelection(types); type.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { types = !types; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Button imp = new Button(sub, SWT.CHECK); imp.setText("Imports"); imp.setSelection(imports); imp.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { imports = !imports; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Button doc = new Button(sub, SWT.CHECK); GridData gd = bdg; gd.horizontalSpan = 2; doc.setLayoutData(gd); doc.setText("Documentation strings"); doc.setSelection(docs); doc.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { docs = !docs; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); sub = new Group(outer, SWT.SHADOW_ETCHED_IN); sub.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false)); sub.setText("Search In"); sub.setLayout(new GridLayout()); Button inSources = new Button(sub, SWT.CHECK); inSources.setText("Project sources"); inSources.setSelection(sources); inSources.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { sources = !sources; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Button inArchives = new Button(sub, SWT.CHECK); inArchives.setText("Source archives"); inArchives.setSelection(archives); inArchives.addSelectionListener( new SelectionListener() { @Override public void widgetSelected(SelectionEvent event) { archives = !archives; } @Override public void widgetDefaultSelected(SelectionEvent event) {} }); Link link = new Link(sub, 0); link.setText("<a>Configure filters...</a>"); link.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { PreferenceDialog preferenceDialog = createPreferenceDialogOn(getShell(), CeylonFiltersPreferencePage.ID, new String[] { CeylonFiltersPreferencePage.ID, CeylonOutlinesPreferencePage.ID }, null); preferenceDialog.setBlockOnOpen(false); preferenceDialog.open(); } }); } @Override public boolean performAction() { saveSearchPattern(); String[] projectNames = null; List<IResource> resources = null; switch (container.getSelectedScope()) { case WORKSPACE_SCOPE: break; case SELECTED_PROJECTS_SCOPE: //called "Enclosing Projects" in the UI projectNames = container.getSelectedProjectNames(); break; case SELECTION_SCOPE: //the resources selected in the view with focus resources = new ArrayList<IResource>(); ISelection selection = container.getSelection(); if (selection instanceof IStructuredSelection && !selection.isEmpty()) { IStructuredSelection ss = (IStructuredSelection) selection; for (@SuppressWarnings("unchecked") Iterator<Object> it = ss.iterator(); it.hasNext();) { Object elem = it.next(); if (elem instanceof IAdaptable) { IAdaptable a = (IAdaptable) elem; IResource resource = (IResource) a.getAdapter(IResource.class); if (resource!=null && resource.isAccessible()) { resources.add(resource); } } } } break; case WORKING_SET_SCOPE: for (IWorkingSet ws: container.getSelectedWorkingSets()) { resources = new ArrayList<IResource>(); for (IAdaptable a: ws.getElements()) { IResource resource = (IResource) a.getAdapter(IResource.class); if (resource!=null && resource.isAccessible()) { resources.add(resource); } } } break; default: MessageDialog.openError(getShell(), "Ceylon Search Error", "Unsupported scope"); return false; } CeylonSearchQuery query = new CeylonSearchQuery( searchPattern, projectNames, resources==null ? null : resources.toArray(NO_RESOURCES), references, types, declarations, imports, docs, caseSensitive, regex, sources, archives, kinds); NewSearchUI.runQueryInBackground(query); return true; } private void initSearchPattern() { searchPattern = ""; IEditorPart currentEditor = getCurrentEditor(); if (currentEditor instanceof TextEditor) { TextEditor textEditor = (TextEditor) currentEditor; String text = getSelectionText(textEditor); if (text!=null) { StringTokenizer tokens = new StringTokenizer(text); if (tokens.hasMoreTokens()) { searchPattern = tokens.nextToken(); } } } if ("".equals(searchPattern) && !previousPatterns.isEmpty()) { searchPattern = previousPatterns.get(0); } } public void saveSearchPattern() { if (previousPatterns.isEmpty() || !previousPatterns.get(0) .equals(searchPattern)) { previousPatterns.add(0, searchPattern); if (previousPatterns.size()>10) { previousPatterns.remove(10); } } } @Override public void setContainer(ISearchPageContainer searchContainer) { container = searchContainer; } @Override public void setVisible(boolean visible) { container.setPerformActionEnabled(true); super.setVisible(visible); } }