/**
* Copyright (c) 2005-2010 Aptana, Inc.
*
* 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. If redistributing this code,
* this entire header must remain intact.
*/
package com.aptana.ide.search.epl;
import java.lang.reflect.Method;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.search.internal.ui.SearchMessages;
import org.eclipse.search.internal.ui.SearchPlugin;
import org.eclipse.search.internal.ui.text.FileSearchPage;
import org.eclipse.search.internal.ui.text.FileSearchResult;
import org.eclipse.search.internal.ui.text.ReplaceAction;
import org.eclipse.search.internal.ui.text.TextSearchPage;
import org.eclipse.search.internal.ui.util.SWTUtil;
import org.eclipse.search.ui.ISearchPageContainer;
import org.eclipse.search.ui.ISearchQuery;
import org.eclipse.search.ui.ISearchResultPage;
import org.eclipse.search.ui.ISearchResultViewPart;
import org.eclipse.search.ui.NewSearchUI;
import org.eclipse.search.ui.text.FileTextSearchScope;
import org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Widget;
import com.aptana.ide.core.IdeLog;
import com.aptana.ide.core.StringUtils;
import com.aptana.ide.search.epl.filesystem.ui.text.FileSystemReplaceAction;
import com.aptana.ide.search.epl.filesystem.ui.text.FileSystemSearchPage;
/**
* @author Pavel Petrochenko
*/
public class AptanaTextSearchPage extends TextSearchPage {
/**
* EXTENSION_POINT_ID
*/
public static final String EXTENSION_POINT_ID = "com.aptana.ide.search.epl.internal.ui.text.TextSearchPage"; //$NON-NLS-1$
/**
* Selection listener for scope controls.
*
* @author Denis Denisenko
*
*/
private class ScopeSelectionListener implements SelectionListener {
/**
* {@inheritDoc}
*/
public void widgetDefaultSelected(SelectionEvent e) {
}
/**
* {@inheritDoc}
*/
public void widgetSelected(SelectionEvent e) {
if (!AptanaTextSearchPage.this.firstOpen) {
return;
}
Widget widget = e.widget;
if (widget != null) {
Object data = widget.getData();
if (data != null && data instanceof Integer) {
scope = ((Integer) data).intValue();
}
}
}
}
/**
* Directory scope.
*/
private static final int DIRECTORY_SCOPE = 12;
/**
* Open files scope.
*/
private static final int OPEN_FILES_SCOPE = 13;
/**
* Scope selection listener.
*/
private ScopeSelectionListener scopeSelectionListener = new ScopeSelectionListener();
// Dialog store id constants
private static final String PAGE_NAME = "TextSearchPage"; //$NON-NLS-1$
private static final String STORE_SEARCH_DIRECTORY = "SEARCH_DIRECTORY"; //$NON-NLS-1$
/**
* Search scope configuration constant.
*/
private static final String SEARCH_SCOPE = "SEARCH_SCOPE"; //$NON-NLS-1$
private ISearchPageContainer fContainer;
private Text fDirectory;
private Button fSearchInDirectory;
private Button fSearchInOpenFiles;
private String fSearchDirectory;
/**
* Search scope.
*/
private int scope;
private boolean firstOpen;
public static class TextSearchPageInput extends TextSearchInput {
private final String fSearchText;
private final boolean fIsCaseSensitive;
private final boolean fIsRegEx;
private final FileTextSearchScope fScope;
private final boolean isDirectory;
private final String directory;
private final boolean isOpenFiles;
private boolean fIsIgnoreLineEndings;
public boolean doRefresh;
/**
* @return
*/
public boolean isDirectory() {
return this.isDirectory;
}
/**
* @return
*/
public String getDirectory() {
return this.directory;
}
/**
* @return should search ignore line endings
*/
public boolean isIgnoreLineEndings() {
return fIsIgnoreLineEndings;
}
/**
* @return
*/
public boolean isOpenFiles() {
return this.isOpenFiles;
}
/**
* @param searchText
* @param isCaseSensitive
* @param isRegEx
* @param scope
* @param isDir
* @param directory
* @param openFiles
* @param isIgnoreLineEndings
*/
public TextSearchPageInput(String searchText, boolean isCaseSensitive,
boolean isRegEx, FileTextSearchScope scope, boolean isDir,
String directory, boolean openFiles, boolean isIgnoreLineEndings) {
this.fSearchText = searchText;
this.isDirectory = isDir;
this.directory = directory;
this.isOpenFiles = openFiles;
this.fIsCaseSensitive = isCaseSensitive;
this.fIsRegEx = isRegEx;
this.fScope = scope;
this.fIsIgnoreLineEndings = isIgnoreLineEndings;
}
/**
* @see org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput#getSearchText()
*/
public String getSearchText() {
return this.fSearchText;
}
/**
* @see org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput#isCaseSensitiveSearch()
*/
public boolean isCaseSensitiveSearch() {
return this.fIsCaseSensitive;
}
/**
* @see org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput#isRegExSearch()
*/
public boolean isRegExSearch() {
return this.fIsRegEx;
}
/**
* @see org.eclipse.search.ui.text.TextSearchQueryProvider.TextSearchInput#getScope()
*/
public FileTextSearchScope getScope() {
return this.fScope;
}
public boolean isRefresh() {
return doRefresh;
}
}
private ISearchQuery newTextQuery() throws CoreException {
Method method;
try {
method = TextSearchPage.class.getDeclaredMethod(
"newQuery", (Class[]) null); //$NON-NLS-1$
method.setAccessible(true);
org.eclipse.search.internal.ui.text.FileSearchQuery query = (org.eclipse.search.internal.ui.text.FileSearchQuery) method
.invoke(this, (Object[]) null);
TextSearchPageInput input = new TextSearchPageInput(query
.getSearchString(), query.isCaseSensitive(), query
.isRegexSearch(), query.getSearchScope(),
isSearchingInDirectory(), getDirectoryText(),
isSearchingInOpenFiles(), false);
return (new AptanaTextSearchQueryProvider()).createQuery(input);
} catch (Exception e) {
}
return null;
}
/**
* @see org.eclipse.search.internal.ui.text.TextSearchPage#performAction()
*/
public boolean performAction() {
try {
NewSearchUI.runQueryInBackground(newTextQuery());
} catch (CoreException e) {
ErrorDialog
.openError(
this.getShell(),
SearchMessages.TextSearchPage_replace_searchproblems_title,
SearchMessages.TextSearchPage_replace_searchproblems_message,
e.getStatus());
return false;
}
return true;
}
/**
* @see org.eclipse.search.internal.ui.text.TextSearchPage#performReplace()
*/
public boolean performReplace() {
try {
IStatus status = NewSearchUI.runQueryInForeground(getContainer()
.getRunnableContext(), newTextQuery());
if (status.matches(IStatus.CANCEL)) {
return false;
}
if (!status.isOK()) {
ErrorDialog
.openError(
getShell(),
SearchMessages.TextSearchPage_replace_searchproblems_title,
SearchMessages.TextSearchPage_replace_runproblem_message,
status);
}
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
ISearchResultViewPart view = NewSearchUI
.activateSearchResultView();
if (view != null) {
ISearchResultPage page = view.getActivePage();
if (page instanceof FileSearchPage) {
FileSearchPage filePage = (FileSearchPage) page;
new ReplaceAction(filePage.getSite().getShell(),
(FileSearchResult) filePage.getInput(),
null, true).run();
} else if (page instanceof FileSystemSearchPage) {
FileSystemSearchPage filePage = (FileSystemSearchPage) page;
new FileSystemReplaceAction(filePage.getSite()
.getShell(),
(FileSystemSearchResult) filePage
.getInput(), null, true).run();
}
}
}
});
return true;
} catch (CoreException e) {
ErrorDialog
.openError(
getShell(),
SearchMessages.TextSearchPage_replace_searchproblems_title,
SearchMessages.TextSearchPage_replace_querycreationproblem_message,
e.getStatus());
return false;
}
}
private boolean isSearchingInOpenFiles() {
if (fSearchInOpenFiles == null) {
IdeLog.logError(Activator.getDefault(),
"Search in open files is null"); //$NON-NLS-1$
return false;
}
return fSearchInOpenFiles.getSelection();
}
private String getDirectoryText() {
return fDirectory.getText();
}
private boolean isSearchingInDirectory() {
if (fSearchInDirectory == null) {
IdeLog.logError(Activator.getDefault(),
"Search in directory is null"); //$NON-NLS-1$
return false;
}
return this.fSearchInDirectory.getSelection();
}
/**
* @see org.eclipse.search.internal.ui.text.TextSearchPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(final Composite parent) {
super.createControl(parent);
readConfiguration();
final Composite result = (Composite) parent.getChildren()[0];
result.setLayoutData(new GridData(GridData.FILL_BOTH));
parent.addControlListener(new ControlListener() {
public void controlMoved(ControlEvent e) {
}
public void controlResized(ControlEvent e) {
modifyScope(parent, result);
}
});
Point computeSize = parent.getShell().computeSize(-1, -1);
Point size = parent.getShell().getSize();
parent.getShell().setMinimumSize(computeSize);
if (size.x < computeSize.x || size.y < computeSize.y) {
parent.getShell().setSize(computeSize.x, computeSize.y);
}
parent.getDisplay().asyncExec(new Runnable() {
public void run() {
modifyScope(parent, result);
parent.getShell().layout(true, true);
}
});
}
/**
* @see org.eclipse.search.internal.ui.text.TextSearchPage#setContainer(org.eclipse.search.ui.ISearchPageContainer)
*/
public void setContainer(ISearchPageContainer container) {
fContainer = container;
super.setContainer(container);
}
private ISearchPageContainer getContainer() {
return fContainer;
}
/**
* @see org.eclipse.jface.dialogs.DialogPage#dispose()
*/
public void dispose() {
writeConfiguration();
super.dispose();
}
/**
* Returns the page settings for this Text search page.
*
* @return the page settings to be used
*/
private IDialogSettings getDialogSettings() {
return SearchPlugin.getDefault().getDialogSettingsSection(
AptanaTextSearchPage.PAGE_NAME);
}
/**
* Initializes itself from the stored page settings.
*/
private void readConfiguration() {
IDialogSettings s = getDialogSettings();
try {
this.scope = s.getInt(SEARCH_SCOPE);
} catch (Exception ex) {
// setting default scope.
this.scope = ISearchPageContainer.WORKSPACE_SCOPE;
}
this.fSearchDirectory = s
.get(AptanaTextSearchPage.STORE_SEARCH_DIRECTORY);
if (this.fSearchDirectory == null) {
this.fSearchDirectory = ""; //$NON-NLS-1$
}
}
/**
* Stores it current configuration in the dialog store.
*/
private void writeConfiguration() {
IDialogSettings s = getDialogSettings();
s.put(AptanaTextSearchPage.STORE_SEARCH_DIRECTORY,
this.fSearchDirectory);
s.put(SEARCH_SCOPE, scope);
}
private void modifyScope(final Composite parent, final Composite result) {
try {
IdeLog.logInfo(Activator.getDefault(), StringUtils.format(
"Accessing children of ", //$NON-NLS-1$
new Object[] { parent.toString() }));
Control[] children = parent.getChildren();
IdeLog.logInfo(Activator.getDefault(), StringUtils.format(
"children taken ", new Object[] { parent.toString() })); //$NON-NLS-1$
try {
for (int a = 0; a < children.length; a++) {
if (children[a] != result && !firstOpen) {
IdeLog.logInfo(Activator.getDefault(),
"Search in directory UI is creating"); //$NON-NLS-1$
firstOpen = true;
children = ((Composite) children[a]).getChildren();
final Group scopeGroup = (Group) children[0];
Control[] children2 = scopeGroup.getChildren();
for (Control control2 : children2) {
if (control2 instanceof Button) {
Button m = (Button) control2;
if ((m.getStyle() & SWT.RADIO) != 0) {
m
.addSelectionListener(scopeSelectionListener);
}
if ((m.getStyle() & SWT.PUSH) != 0) {
GridData gridData = new GridData();
m.setLayoutData(gridData);
gridData.widthHint = SWTUtil
.getButtonWidthHint(m);
m.setLayoutData(gridData);
}
}
}
fSearchInDirectory = new Button(scopeGroup, SWT.RADIO);
fSearchInDirectory.setText(Messages.DIRECTORY);
fSearchInDirectory
.addSelectionListener(scopeSelectionListener);
fSearchInDirectory
.setData(new Integer(DIRECTORY_SCOPE));
IdeLog.logInfo(Activator.getDefault(),
"Search in directory UI is nearly created"); //$NON-NLS-1$
fDirectory = new Text(scopeGroup, SWT.READ_ONLY
| SWT.BORDER);
GridData gridData = new GridData(
GridData.FILL_HORIZONTAL);
gridData.horizontalIndent = 8;
gridData.horizontalSpan = 2;
fDirectory.setLayoutData(gridData);
fDirectory.setText(fSearchDirectory);
IdeLog.logInfo(Activator.getDefault(),
"Search in directory was created"); //$NON-NLS-1$
Button choose = new Button(scopeGroup, SWT.PUSH);
choose.setText(Messages.CHOOSE);
choose.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
DirectoryDialog ddialog = new DirectoryDialog(
fSearchInDirectory.getShell(), SWT.NONE);
String open = ddialog.open();
if (open != null) {
fSearchDirectory = open;
writeConfiguration();
fDirectory.setText(open);
if (fSearchInDirectory.getSelection()) {
getContainer()
.setPerformActionEnabled(
fDirectory.getText()
.length() > 0);
}
}
}
});
fSearchInOpenFiles = new Button(scopeGroup, SWT.RADIO);
fSearchInOpenFiles
.addSelectionListener(scopeSelectionListener);
fSearchInOpenFiles.setText(Messages.OPEN_EDITORS);
fSearchInOpenFiles
.setData(new Integer(OPEN_FILES_SCOPE));
fSearchInOpenFiles.setLayoutData(new GridData(SWT.LEFT,
SWT.CENTER, false, false));
GridData gridData2 = new GridData();
gridData2.widthHint = SWTUtil
.getButtonWidthHint(choose);
choose.setLayoutData(gridData2);
fSearchInDirectory
.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(
SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
boolean selection = fSearchInDirectory
.getSelection();
if (!selection) {
getContainer()
.setPerformActionEnabled(
true);
return;
}
getContainer().setSelectedScope(1);
Control[] c = scopeGroup.getChildren();
for (Control cm : c) {
if (cm instanceof Button) {
Button b = (Button) cm;
if (b != fSearchInDirectory) {
if (b.getSelection()) {
b.setSelection(false);
}
}
}
}
getContainer()
.setPerformActionEnabled(
fDirectory.getText()
.length() > 0);
}
});
scopeGroup.layout(true, true);
selectCurrentScope();
break;
}
}
if (fSearchInDirectory == null) {
IdeLog.logError(Activator.getDefault(),
"Search in directory UI was not created"); //$NON-NLS-1$
}
} catch (Throwable e) {
IdeLog.logError(Activator.getDefault(),
"Exception while modifing scope", e); //$NON-NLS-1$
}
} catch (Throwable e) {
IdeLog.logError(Activator.getDefault(),
"Exception on top of modifing scope", e); //$NON-NLS-1$
}
}
/**
* Selects current scope.
*/
private void selectCurrentScope() {
if (fSearchInDirectory != null) {
Composite parent = fSearchInDirectory.getParent();
Control[] children = parent.getChildren();
for (Control child : children) {
if (child instanceof Button) {
final Button btn = (Button) child;
if ((btn.getStyle() & SWT.RADIO) != 0) {
Object data = btn.getData();
if (data != null && data instanceof Integer) {
if (((Integer) data).intValue() == scope) {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
btn.setSelection(true);
}
});
break;
} else {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
btn.setSelection(false);
}
});
}
}
}
}
}
}
}
}