/******************************************************************************* * Copyright © 2004, 2013 IBM Corporation and others. * 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: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.ui.internal.search; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.edt.ide.core.model.IEGLElement; import org.eclipse.edt.ide.core.search.IEGLSearchConstants; import org.eclipse.edt.ide.core.search.IEGLSearchScope; import org.eclipse.edt.ide.core.search.SearchEngine; import org.eclipse.edt.ide.ui.EDTUIPlugin; import org.eclipse.edt.ide.ui.internal.IUIHelpConstants; import org.eclipse.edt.ide.ui.internal.RowLayouter; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.search.ui.ISearchPage; import org.eclipse.search.ui.ISearchPageContainer; import org.eclipse.search.ui.ISearchResultViewEntry; 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.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.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.model.IWorkbenchAdapter; public class EGLSearchPage extends DialogPage implements ISearchPage, IEGLSearchConstants { public static final String EXTENSION_POINT_ID= "org.eclipse.edt.ide.ui.search.EGLSearchPage"; //$NON-NLS-1$ // Dialog store id constants private final static String PAGE_NAME= "EGLSearchPage"; //$NON-NLS-1$ private final static String STORE_CASE_SENSITIVE= PAGE_NAME + "CASE_SENSITIVE"; //$NON-NLS-1$ private static List fgPreviousSearchPatterns= new ArrayList(20); private SearchPatternData fInitialData; private IStructuredSelection fStructuredSelection; private IEGLElement feglElement; private boolean fFirstTime= true; private IDialogSettings fDialogSettings; private boolean fIsCaseSensitive; private Combo fPattern; private ISearchPageContainer fContainer; private Button fCaseSensitive; private Button[] fSearchFor; private int[] fSearchForValues = { PROGRAM_PART, ALL_FUNCTIONS, LIBRARY_PART, RECORD_PART, HANDLER_PART, SERVICE_PART, INTERFACE_PART, DELEGATE_PART, EXTERNALTYPE_PART, ENUMERATION_PART, CLASS_PART, ANNOTATION_PART, STEREOTYPE_PART, ALL_ELEMENTS }; private String[] fSearchForText= { EGLSearchMessages.EGLSearchPageSearchForProgram, EGLSearchMessages.EGLSearchPageSearchForFunction, EGLSearchMessages.EGLSearchPageSearchForLibrary, EGLSearchMessages.EGLSearchPageSearchForRecord, EGLSearchMessages.EGLSearchPageSearchForHandler, EGLSearchMessages.EGLSearchPageSearchForService, EGLSearchMessages.EGLSearchPageSearchForInterface, EGLSearchMessages.EGLSearchPageSearchForDelegate, EGLSearchMessages.EGLSearchPageSearchForExternalType, EGLSearchMessages.EGLSearchPageSearchForEnum, EGLSearchMessages.EGLSearchPageSearchForClass, EGLSearchMessages.EGLSearchPageSearchForAnnotation, EGLSearchMessages.EGLSearchPageSearchForStereotype, EGLSearchMessages.EGLSearchPageSearchForAny }; private Button[] fLimitTo; private int[] fLimitToValues = { DECLARATIONS, REFERENCES, ALL_OCCURRENCES }; private String[] fLimitToText= { EGLSearchMessages.EGLSearchPageLimitToDeclarations, EGLSearchMessages.EGLSearchPageLimitToReferences, EGLSearchMessages.EGLSearchPageLimitToAllOccurrences }; private static class SearchPatternData { int searchFor; int limitTo; String pattern; boolean isCaseSensitive; IEGLElement eglElement; int scope; IWorkingSet[] workingSets; public SearchPatternData(int s, int l, boolean i, String p, IEGLElement element) { this(s, l, p, i, element, ISearchPageContainer.WORKSPACE_SCOPE, null); } public SearchPatternData(int s, int l, String p, boolean i, IEGLElement element, int scope, IWorkingSet[] workingSets) { searchFor= s; limitTo= l; pattern= p; isCaseSensitive= i; eglElement= element; this.scope = scope; this.workingSets = workingSets; } } public boolean performNewSearch() { org.eclipse.search.ui.NewSearchUI.activateSearchResultView(); SearchPatternData patternData= getPatternData(); // Setup search scope IEGLSearchScope scope= null; String scopeDescription= ""; //$NON-NLS-1$ switch (getContainer().getSelectedScope()) { case ISearchPageContainer.WORKSPACE_SCOPE: scopeDescription= EGLSearchMessages.WorkspaceScope; scope= SearchEngine.createWorkspaceScope(); break; case ISearchPageContainer.SELECTION_SCOPE: scopeDescription= EGLSearchMessages.SelectionScope; scope= EGLSearchScopeFactory.getInstance().createEGLSearchScope(fStructuredSelection); break; case ISearchPageContainer.SELECTED_PROJECTS_SCOPE: scope= EGLSearchScopeFactory.getInstance().createEGLProjectSearchScope(fStructuredSelection); IProject[] projects= EGLSearchScopeFactory.getInstance().getProjects(scope); if (projects.length >= 1) { if (projects.length == 1) scopeDescription= EGLSearchMessages.bind(EGLSearchMessages.EnclosingProjectScope, projects[0].getName()); //$NON-NLS-1$ else scopeDescription= EGLSearchMessages.bind(EGLSearchMessages.EnclosingProjectsScope, projects[0].getName()); //$NON-NLS-1$ } else scopeDescription= EGLSearchMessages.bind(EGLSearchMessages.EnclosingProjectScope, ""); //$NON-NLS-1$ //$NON-NLS-2$ break; case ISearchPageContainer.WORKING_SET_SCOPE: IWorkingSet[] workingSets= getContainer().getSelectedWorkingSets(); // should not happen - just to be sure if (workingSets == null || workingSets.length < 1) return false; scopeDescription=EGLSearchMessages.bind(EGLSearchMessages.WorkingSetScope, SearchUtil.toString(workingSets)); scope= EGLSearchScopeFactory.getInstance().createEGLSearchScope(getContainer().getSelectedWorkingSets()); //SearchUtil.updateLRUWorkingSets(getContainer().getSelectedWorkingSets()); } EGLSearchQuery wsJob = new EGLSearchQuery(patternData.pattern, patternData.isCaseSensitive, patternData.searchFor, patternData.limitTo, scope, scopeDescription,false); NewSearchUI.activateSearchResultView(); NewSearchUI.runQueryInBackground(wsJob); return true; } public boolean performAction() { return performNewSearch(); } private int getLimitTo() { for (int i= 0; i < fLimitTo.length; i++) { if (fLimitTo[i].getSelection()) return fLimitToValues[ i ]; } return UNKNOWN; } private void setLimitTo(int searchFor ) { for( int i = 0; i < fLimitTo.length; i++ ) fLimitTo[ i ].setEnabled( true ); } private String[] getPreviousSearchPatterns() { // Search results are not persistent int patternCount= fgPreviousSearchPatterns.size(); String [] patterns= new String[patternCount]; for (int i= 0; i < patternCount; i++) patterns[i]= ((SearchPatternData) fgPreviousSearchPatterns.get(patternCount - 1 - i)).pattern; return patterns; } private int getSearchFor() { for (int i= 0; i < fSearchFor.length; i++) { if (fSearchFor[i].getSelection()) return fSearchForValues[ i ] ; } return UNKNOWN; } private String getPattern() { return fPattern.getText(); } /** * Return search pattern data and update previous searches. * An existing entry will be updated. */ private SearchPatternData getPatternData() { String pattern= getPattern(); SearchPatternData match= null; int i= 0; int size= fgPreviousSearchPatterns.size(); while (match == null && i < size) { match= (SearchPatternData) fgPreviousSearchPatterns.get(i); i++; if (!pattern.equals(match.pattern)) match= null; }; if (match == null) { match= new SearchPatternData( getSearchFor(), getLimitTo(), pattern, fCaseSensitive.getSelection(), feglElement, getContainer().getSelectedScope(), getContainer().getSelectedWorkingSets()); fgPreviousSearchPatterns.add(match); } else { match.searchFor= getSearchFor(); match.limitTo= getLimitTo(); match.isCaseSensitive= fCaseSensitive.getSelection(); match.eglElement= feglElement; match.scope= getContainer().getSelectedScope(); match.workingSets= getContainer().getSelectedWorkingSets(); }; return match; } /* * Implements method from IDialogPage */ public void setVisible(boolean visible) { if (visible && fPattern != null) { if (fFirstTime) { fFirstTime= false; // Set item and text here to prevent page from resizing fPattern.setItems(getPreviousSearchPatterns()); initSelections(); } fPattern.setFocus(); getContainer().setPerformActionEnabled(fPattern.getText().length() > 0); } super.setVisible(visible); } public boolean isValid() { return true; } //---- Widget creation ------------------------------------------------ /** * Creates the page's content. */ public void createControl(Composite parent) { initializeDialogUnits(parent); readConfiguration(); GridData gd; Composite result= new Composite(parent, SWT.NONE); GridLayout layout= new GridLayout(2, false); layout.horizontalSpacing= 10; result.setLayout(layout); result.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); RowLayouter layouter= new RowLayouter(layout.numColumns); gd= new GridData(); gd.horizontalAlignment= GridData.FILL; gd.verticalAlignment= GridData.VERTICAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_FILL; layouter.setDefaultGridData(gd, 0); layouter.setDefaultGridData(gd, 1); layouter.setDefaultSpan(); layouter.perform(createExpression(result)); layouter.perform(createSearchFor(result), createLimitTo(result), -1); SelectionAdapter eglElementInitializer= new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (getSearchFor() == fInitialData.searchFor) feglElement= fInitialData.eglElement; else feglElement= null; //handleAllElements(event); setLimitTo(getSearchFor()); updateCaseSensitiveCheckbox(); } }; int icnt = fSearchFor.length; for(int x=0; x<icnt; x++) fSearchFor[x].addSelectionListener(eglElementInitializer); setControl(result); Dialog.applyDialogFont(result); PlatformUI.getWorkbench().getHelpSystem().setHelp(result, IUIHelpConstants.EGL_SEARCH_DIALOG); } private Control createExpression(Composite parent) { Composite result= new Composite(parent, SWT.NONE); GridLayout layout= new GridLayout(2, false); result.setLayout(layout); GridData gd= new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); gd.horizontalSpan= 2; gd.horizontalIndent= 0; result.setLayoutData(gd); // Pattern text + info Label label= new Label(result, SWT.LEFT); label.setText(EGLSearchMessages.EGLSearchPageExpressionLabel); gd= new GridData(GridData.BEGINNING); gd.horizontalSpan= 2; // gd.horizontalIndent= -gd.horizontalIndent; label.setLayoutData(gd); // Pattern combo fPattern= new Combo(result, SWT.SINGLE | SWT.BORDER); fPattern.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { handlePatternSelected(); } }); fPattern.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { getContainer().setPerformActionEnabled(getPattern().length() > 0); updateCaseSensitiveCheckbox(); } }); gd= new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL); gd.horizontalIndent= -gd.horizontalIndent; fPattern.setLayoutData(gd); // Ignore case checkbox fCaseSensitive= new Button(result, SWT.CHECK); fCaseSensitive.setText(EGLSearchMessages.EGLSearchPageExpressionCaseSensitive); gd= new GridData(); fCaseSensitive.setLayoutData(gd); fCaseSensitive.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { fIsCaseSensitive= fCaseSensitive.getSelection(); writeConfiguration(); } }); return result; } private void updateCaseSensitiveCheckbox() { if (fInitialData != null && getPattern().equals(fInitialData.pattern) && feglElement != null) { fCaseSensitive.setEnabled(false); fCaseSensitive.setSelection(true); } else { fCaseSensitive.setEnabled(true); fCaseSensitive.setSelection(fIsCaseSensitive); } } private void handlePatternSelected() { if( fPattern.getSelectionIndex() < 0 ) return; int index = fgPreviousSearchPatterns.size() - 1 - fPattern.getSelectionIndex(); fInitialData = (SearchPatternData) fgPreviousSearchPatterns.get( index ); updateSelections(); if( fInitialData.workingSets != null ) getContainer().setSelectedWorkingSets( fInitialData.workingSets ); else getContainer().setSelectedScope( fInitialData.scope ); } private void updateSelections(){ if (fInitialData == null) fInitialData = trySimpleTextSelection( getContainer().getSelection() ); if (fInitialData == null) fInitialData = getDefaultInitValues(); feglElement = fInitialData.eglElement; fIsCaseSensitive = fInitialData.isCaseSensitive; fCaseSensitive.setSelection( fInitialData.isCaseSensitive ); fCaseSensitive.setEnabled( fInitialData.eglElement == null ); //HashSet set = new HashSet( fInitialData.searchFor ); //boolean enabled = ! set.contains( fSearchForValues[ fSearchFor.length - 1 ] ); for (int i = 0; i < fSearchFor.length; i++){ fSearchFor[i].setSelection( fSearchForValues[i] == fInitialData.searchFor ); //fSearchFor[i].setEnabled( enabled ); } // if( !enabled ) // fSearchFor[ fSearchFor.length - 1 ].setEnabled( true ); setLimitTo( fInitialData.searchFor ); for (int i = 0; i < fLimitTo.length; i++) fLimitTo[i].setSelection( fLimitToValues[i] == fInitialData.limitTo ); fPattern.setText( fInitialData.pattern ); } private Control createSearchFor(Composite parent) { Group result= new Group(parent, SWT.NONE); result.setText(EGLSearchMessages.EGLSearchPageSearchForLabel); GridLayout layout= new GridLayout(); layout.numColumns= 5; result.setLayout(layout); fSearchFor= new Button[fSearchForText.length]; for (int i= 0; i < fSearchForText.length; i++) { Button button= new Button(result, SWT.RADIO); button.setText(fSearchForText[i]); fSearchFor[i]= button; } return result; } private Control createLimitTo(Composite parent) { Group result= new Group(parent, SWT.NONE); result.setText(EGLSearchMessages.EGLSearchPageLimitToLabel); GridLayout layout= new GridLayout(); layout.numColumns= 1; result.setLayout(layout); fLimitTo= new Button[fLimitToText.length]; for (int i= 0; i < fLimitToText.length; i++) { Button button= new Button(result, SWT.RADIO); button.setText(fLimitToText[i]); fLimitTo[i]= button; } return result; } private void initSelections() { fStructuredSelection = asStructuredSelection(); fInitialData = tryStructuredSelection( fStructuredSelection ); updateSelections(); } private SearchPatternData tryStructuredSelection(IStructuredSelection selection) { if( selection == null || selection.size() > 1 ) return null; Object o = selection.getFirstElement(); if( o instanceof IEGLElement ) { return determineInitValuesFrom( (IEGLElement)o ); } else if( o instanceof ISearchResultViewEntry ) { IEGLElement element = SearchUtil.getEGLElement( ((ISearchResultViewEntry)o).getSelectedMarker() ); return determineInitValuesFrom( element ); } else if( o instanceof IAdaptable ) { IEGLElement element = (IEGLElement)((IAdaptable)o).getAdapter( IEGLElement.class ); if( element != null ) { return determineInitValuesFrom( element ); } else { IWorkbenchAdapter adapter= (IWorkbenchAdapter)((IAdaptable)o).getAdapter( IWorkbenchAdapter.class ); if( adapter != null ){ return new SearchPatternData( ALL_ELEMENTS, DECLARATIONS, fIsCaseSensitive, adapter.getLabel(o), null ); } } } return null; } private SearchPatternData determineInitValuesFrom(IEGLElement element) { if (element == null) return null; return null; } private SearchPatternData trySimpleTextSelection(ISelection selection) { SearchPatternData result= null; if (selection instanceof ITextSelection) { BufferedReader reader= new BufferedReader(new StringReader(((ITextSelection)selection).getText())); String text; try { text= reader.readLine(); if (text == null) text= ""; //$NON-NLS-1$ } catch (IOException ex) { text= ""; //$NON-NLS-1$ } result= new SearchPatternData( ALL_ELEMENTS, REFERENCES, fIsCaseSensitive, text, null); } return result; } private SearchPatternData getDefaultInitValues() { return new SearchPatternData(ALL_ELEMENTS, REFERENCES, fIsCaseSensitive, "", null); //$NON-NLS-1$ } /* * Implements method from ISearchPage */ public void setContainer(ISearchPageContainer container) { fContainer= container; } /** * Returns the search page's container. */ private ISearchPageContainer getContainer() { return fContainer; } /** * Returns the structured selection from the selection. */ private IStructuredSelection asStructuredSelection() { IWorkbenchWindow wbWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (wbWindow != null) { IWorkbenchPage page= wbWindow.getActivePage(); if (page != null) { IWorkbenchPart part= page.getActivePart(); if (part != null) try { return getStructuredSelection(part); } catch (Exception ex) { } } } return StructuredSelection.EMPTY; } //--------------- Configuration handling -------------- /** * Returns the page settings for this Java search page. * * @return the page settings to be used */ private IDialogSettings getDialogSettings() { IDialogSettings settings= EDTUIPlugin.getDefault().getDialogSettings(); fDialogSettings= settings.getSection(PAGE_NAME); if (fDialogSettings == null) fDialogSettings= settings.addNewSection(PAGE_NAME); return fDialogSettings; } /** * Initializes itself from the stored page settings. */ private void readConfiguration() { IDialogSettings s= getDialogSettings(); fIsCaseSensitive= s.getBoolean(STORE_CASE_SENSITIVE); } /** * Stores it current configuration in the dialog store. */ private void writeConfiguration() { IDialogSettings s= getDialogSettings(); s.put(STORE_CASE_SENSITIVE, fIsCaseSensitive); } /** * Copied from SelectionConverter.getStructuredSelection(IWorkbenchPart) * * Converts the selection provided by the given part into a structured selection. * The following conversion rules are used: * <ul> * <li><code>part instanceof JavaEditor</code>: returns a structured selection * using code resolve to convert the editor's text selection.</li> * <li><code>part instanceof IWorkbenchPart</code>: returns the part's selection * if it is a structured selection.</li> * <li><code>default</code>: returns an empty structured selection.</li> * </ul> */ public IStructuredSelection getStructuredSelection(IWorkbenchPart part) { //throws JavaModelException { ISelectionProvider provider= part.getSite().getSelectionProvider(); if (provider != null) { ISelection selection= provider.getSelection(); if (selection instanceof IStructuredSelection) return (IStructuredSelection)selection; } return StructuredSelection.EMPTY; } }