blob: ed5c2c4036f80d7d6e0b645314f9b90a3dcd7dd0 [file] [log] [blame]
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
package org.eclipse.search.internal.ui.text;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
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.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.model.IWorkbenchAdapter;
import org.eclipse.search.ui.ISearchPage;
import org.eclipse.search.ui.ISearchPageContainer;
import org.eclipse.search.ui.ISearchResultViewEntry;
import org.eclipse.search.ui.IWorkingSet;
import org.eclipse.search.ui.SearchUI;
import org.eclipse.search.internal.core.text.TextSearchScope;
import org.eclipse.search.internal.ui.ISearchHelpContextIds;
import org.eclipse.search.internal.ui.SearchMessages;
import org.eclipse.search.internal.ui.SearchPlugin;
import org.eclipse.search.internal.ui.util.ExceptionHandler;
import org.eclipse.search.internal.ui.util.FileTypeEditor;
import org.eclipse.search.internal.ui.util.RowLayouter;
import org.eclipse.search.internal.ui.util.SWTUtil;
public class TextSearchPage extends DialogPage implements ISearchPage {
public static final String EXTENSION_POINT_ID= "org.eclipse.search.internal.ui.text.TextSearchPage"; //$NON-NLS-1$
// Dialog store id constants
private final static String PAGE_NAME= "TextSearchPage"; //$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 IDialogSettings fDialogSettings;
private boolean fFirstTime= true;
private boolean fIsCaseSensitive;
private Combo fPattern;
private Button fIgnoreCase;
private Combo fExtensions;
private ISearchPageContainer fContainer;
private FileTypeEditor fFileTypeEditor;
private static class SearchPatternData {
boolean ignoreCase;
String pattern;
Set extensions;
int scope;
IWorkingSet workingSet;
public SearchPatternData(String pattern, boolean ignoreCase, Set extensions, int scope, IWorkingSet workingSet) {
this.ignoreCase= ignoreCase;
this.pattern= pattern;
this.extensions= extensions;
this.scope= scope;
this.workingSet= workingSet;
}
}
//---- Action Handling ------------------------------------------------
public boolean performAction() {
SearchUI.activateSearchResultView();
SearchPatternData patternData= getPatternData();
if (patternData.pattern == null || patternData.pattern.length() == 0)
return true;
// Setup search scope
TextSearchScope scope= null;
switch (getContainer().getSelectedScope()) {
case ISearchPageContainer.WORKSPACE_SCOPE:
scope= TextSearchScope.newWorkspaceScope();
break;
case ISearchPageContainer.SELECTION_SCOPE:
scope= getSelectedResourcesScope();
break;
case ISearchPageContainer.WORKING_SET_SCOPE:
IWorkingSet workingSet= getContainer().getSelectedWorkingSet();
String desc= SearchMessages.getFormattedString("WorkingSetScope", workingSet.getName()); //$NON-NLS-1$
scope= new TextSearchScope(desc, workingSet.getResources());
}
scope.addExtensions(patternData.extensions);
TextSearchResultCollector collector= new TextSearchResultCollector();
TextSearchOperation op= new TextSearchOperation(
SearchPlugin.getWorkspace(),
patternData.pattern,
getSearchOptions(),
scope,
collector);
IRunnableContext context= null;
context= getContainer().getRunnableContext();
Shell shell= fPattern.getShell();
if (context == null)
context= new ProgressMonitorDialog(shell);
try {
context.run(true, true, op);
} catch (InvocationTargetException ex) {
ExceptionHandler.handle(ex, SearchMessages.getString("Search.Error.search.title"),SearchMessages.getString("Search.Error.search.message")); //$NON-NLS-2$ //$NON-NLS-1$
return false;
} catch (InterruptedException e) {
return false;
}
return true;
}
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(
pattern,
ignoreCase(),
getExtensions(),
getContainer().getSelectedScope(),
getContainer().getSelectedWorkingSet());
fgPreviousSearchPatterns.add(match);
}
else {
match.ignoreCase= ignoreCase();
match.extensions= getExtensions();
match.scope= getContainer().getSelectedScope();
match.workingSet= getContainer().getSelectedWorkingSet();
};
return match;
}
private String[] getPreviousExtensions() {
List extensions= new ArrayList(fgPreviousSearchPatterns.size());
for (int i= fgPreviousSearchPatterns.size() -1 ; i >= 0; i--) {
SearchPatternData data= (SearchPatternData)fgPreviousSearchPatterns.get(i);
String text= FileTypeEditor.typesToString(data.extensions);
if (!extensions.contains(text))
extensions.add(text);
}
return (String[])extensions.toArray(new String[extensions.size()]);
}
private String[] getPreviousSearchPatterns() {
int size= fgPreviousSearchPatterns.size();
String [] patterns= new String[size];
for (int i= 0; i < size; i++)
patterns[i]= ((SearchPatternData) fgPreviousSearchPatterns.get(size - 1 - i)).pattern;
return patterns;
}
private String getSearchOptions() {
StringBuffer result= new StringBuffer();
if (!ignoreCase())
result.append("i"); //$NON-NLS-1$
return result.toString();
}
private Display getTargetDisplay() {
return fPattern.getDisplay();
}
private Set getExtensions() {
return fFileTypeEditor.getFileTypes();
}
private boolean ignoreCase() {
return fIgnoreCase.getSelection();
}
/*
* 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());
fExtensions.setItems(getPreviousExtensions());
initializePatternControl();
}
fPattern.setFocus();
getContainer().setPerformActionEnabled(fPattern.getText().length() > 0 && getContainer().hasValidScope());
}
super.setVisible(visible);
}
//---- Widget creation ------------------------------------------------
/**
* Creates the page's content.
*/
public void createControl(Composite parent) {
readConfiguration();
GridLayout layout;
GridData gd;
Label label;
RowLayouter layouter;
Composite result= new Composite(parent, SWT.NONE);
result.setLayout(new GridLayout());
// Search Expression
Group group= new Group(result, SWT.NONE);
group.setText(SearchMessages.getString("SearchPage.expression.label")); //$NON-NLS-1$
layout= new GridLayout();
layout.numColumns= 2;
group.setLayout(layout);
layouter= new RowLayouter(2);
layouter.setDefaultSpan();
// Pattern combo
fPattern= new Combo(group, SWT.SINGLE | SWT.BORDER);
// Not done here to prevent page from resizing
// fPattern.setItems(getPreviousSearchPatterns());
fPattern.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleWidgetSelected();
}
});
fPattern.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
getContainer().setPerformActionEnabled(getPattern().length() > 0 && getContainer().hasValidScope());
}
});
gd= new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint= convertWidthInCharsToPixels(30);
fPattern.setLayoutData(gd);
layouter.perform( new Control[] { fPattern }, 0);
label= new Label(group, SWT.LEFT);
label.setText(SearchMessages.getString("SearchPage.expression.pattern")); //$NON-NLS-1$
fIgnoreCase= new Button(group, SWT.CHECK);
fIgnoreCase.setText(SearchMessages.getString("SearchPage.caseSensitive")); //$NON-NLS-1$
gd= new GridData(); gd.horizontalAlignment= gd.END;
fIgnoreCase.setLayoutData(gd);
layouter.perform( new Control[] {label, fIgnoreCase}, -1);
fIgnoreCase.setSelection(!fIsCaseSensitive);
fIgnoreCase.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
fIsCaseSensitive= !fIgnoreCase.getSelection();
writeConfiguration();
}
});
Control control= makeExtensionEditor(group);
layouter.perform( new Control[] { control }, 0);
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
setControl(result);
WorkbenchHelp.setHelp(result, ISearchHelpContextIds.TEXT_SEARCH_PAGE);
}
private void handleWidgetSelected() {
if (fPattern.getSelectionIndex() < 0)
return;
int index= fgPreviousSearchPatterns.size() - 1 - fPattern.getSelectionIndex();
SearchPatternData patternData= (SearchPatternData) fgPreviousSearchPatterns.get(index);
fIgnoreCase.setSelection(patternData.ignoreCase);
fPattern.setText(patternData.pattern);
fFileTypeEditor.setFileTypes(patternData.extensions);
if (patternData.workingSet != null)
getContainer().setSelectedWorkingSet(patternData.workingSet);
else
getContainer().setSelectedScope(patternData.scope);
}
private void initializePatternControl() {
ISelection selection= getSelection();
String text= ""; //$NON-NLS-1$
String extension= null; //$NON-NLS-1$
if (selection instanceof ITextSelection) {
ITextSelection textSelection= (ITextSelection)getSelection();
text= textSelection.getText();
} else {
IResource resource= null;
Object item= null;
if (selection instanceof IStructuredSelection)
item= ((IStructuredSelection)selection).getFirstElement();
if (item instanceof IResource) {
resource= (IResource)item;
text= resource.getName();
}
else if (item instanceof ISearchResultViewEntry) {
IMarker marker= (IMarker)((ISearchResultViewEntry)item).getSelectedMarker();
resource= marker.getResource();
try {
text= (String)marker.getAttribute(SearchUI.LINE);
} catch (CoreException ex) {
ExceptionHandler.handle(ex, SearchMessages.getString("Search.Error.markerAttributeAccess.title"), SearchMessages.getString("Search.Error.markerAttributeAccess.message")); //$NON-NLS-2$ //$NON-NLS-1$
text= ""; //$NON-NLS-1$
}
} else if (item instanceof IAdaptable) {
Object adapter= ((IAdaptable)item).getAdapter(IWorkbenchAdapter.class);
if (adapter instanceof IWorkbenchAdapter)
text= ((IWorkbenchAdapter)adapter).getLabel(item);
adapter= ((IAdaptable)item).getAdapter(IResource.class);
if (adapter instanceof IResource) {
resource= (IResource)adapter;
if (text == null) // keep text, if provided by workbench adapter
text= resource.getName();
}
}
if (resource instanceof IFile ) {
extension= resource.getFileExtension();
if (extension == null)
extension= resource.getName();
else
extension= "*." + extension; //$NON-NLS-1$
}
else
extension= "*"; //$NON-NLS-1$
}
fPattern.setText(insertEscapeChars(text));
if (getPreviousExtensions().length > 0)
fExtensions.setText(getPreviousExtensions()[0]);
else {
if (extension == null)
extension= getExtensionFromEditor();
if (extension != null)
fExtensions.setText(extension);
}
}
private String insertEscapeChars(String text) {
if (text == null || text.equals("")) //$NON-NLS-1$
return ""; //$NON-NLS-1$
StringBuffer sbIn= new StringBuffer(text);
BufferedReader reader= new BufferedReader(new StringReader(text));
int lengthOfFirstLine= 0;
try {
lengthOfFirstLine= reader.readLine().length();
} catch (IOException ex) {
return ""; //$NON-NLS-1$
}
StringBuffer sbOut= new StringBuffer(lengthOfFirstLine + 5);
int i= 0;
while (i < lengthOfFirstLine) {
char ch= sbIn.charAt(i);
if (ch == '*' || ch == '?' || ch == '\\')
sbOut.append("\\"); //$NON-NLS-1$
sbOut.append(ch);
i= i+1;
};
return sbOut.toString();
}
private String getExtensionFromEditor() {
IEditorPart ep= SearchPlugin.getActivePage().getActiveEditor();
if (ep != null) {
Object elem= ep.getEditorInput();
if (elem instanceof IFileEditorInput) {
String extension= ((IFileEditorInput)elem).getFile().getFileExtension();
if (extension == null)
return ((IFileEditorInput)elem).getFile().getName();
else
return "*." + extension; //$NON-NLS-1$
}
}
return null;
}
private Composite makeExtensionEditor(Composite parent) {
Composite result= new Composite(parent, SWT.NONE);
GridLayout layout= new GridLayout();
layout.marginWidth= 0; layout.marginHeight= 0;
layout.numColumns= 3;
result.setLayout(layout);
Label label= new Label(result, SWT.LEFT);
label.setText(SearchMessages.getString("SearchPage.extensions")); //$NON-NLS-1$
// fExtensions= new Text(result, SWT.LEFT | SWT.BORDER);
fExtensions= new Combo(result, SWT.SINGLE | SWT.BORDER);
// fExtensions.addSelectionListener(new SelectionAdapter() {
// public void widgetSelected(SelectionEvent e) {
// handleWidgetSelected();
// }
// });
GridData gd= new GridData(GridData.FILL_HORIZONTAL);
gd.widthHint= convertWidthInCharsToPixels(30);
fExtensions.setLayoutData(gd);
Button button= new Button(result, SWT.PUSH);
button.setText(SearchMessages.getString("SearchPage.browse")); //$NON-NLS-1$
button.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
SWTUtil.setButtonDimensionHint(button);
fFileTypeEditor= new FileTypeEditor(
SearchPlugin.getDefault().getWorkbench().getEditorRegistry(),
fExtensions, button);
return result;
}
public boolean isValid() {
return true;
}
/**
* Sets the search page's container.
*/
public void setContainer(ISearchPageContainer container) {
fContainer= container;
}
/**
* Returns the search page's container.
*/
private ISearchPageContainer getContainer() {
return fContainer;
}
/**
* Returns the current active selection.
*/
private ISelection getSelection() {
return fContainer.getSelection();
}
private TextSearchScope getSelectedResourcesScope() {
TextSearchScope scope= new TextSearchScope(SearchMessages.getString("SelectionScope")); //$NON-NLS-1$
if (getSelection() instanceof IStructuredSelection && !getSelection().isEmpty()) {
Iterator iter= ((IStructuredSelection)getSelection()).iterator();
while (iter.hasNext()) {
Object selection= iter.next();
//Unpack search result entry
if (selection instanceof ISearchResultViewEntry)
selection= ((ISearchResultViewEntry)selection).getGroupByKey();
if (selection instanceof IResource)
scope.add((IResource)selection);
else if (selection instanceof IAdaptable) {
IResource resource= (IResource)((IAdaptable)selection).getAdapter(IResource.class);
if (resource != null)
scope.add(resource);
}
}
}
return scope;
}
//--------------- Configuration handling --------------
/**
* Returns the page settings for this Java search page.
*
* @return the page settings to be used
*/
private IDialogSettings getDialogSettings() {
IDialogSettings settings= SearchPlugin.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);
}
}