/*
* Copyright (c) 2009 Andrejs Jermakovics.
*
* 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:
* Andrejs Jermakovics - initial implementation
*/
package it.unibz.instasearch.prefs;
import it.unibz.instasearch.InstaSearchPlugin;
import it.unibz.instasearch.indexing.WorkspaceIndexer;
import it.unibz.instasearch.indexing.WorkspaceIndexerJDT;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.PathEditor;
import org.eclipse.jface.preference.StringButtonFieldEditor;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.eclipse.ui.dialogs.FilteredResourcesSelectionDialog;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.dialogs.TypeFilteringDialog;
public class InstaSearchPreferencePage
extends FieldEditorPreferencePage
implements IWorkbenchPreferencePage {
public static final String ID = InstaSearchPreferencePage.class.getName();
private BooleanFieldEditor periodicReindexEnabled;
private IntegerFieldEditor periodicReindexInterval;
public InstaSearchPreferencePage() {
super(GRID);
setPreferenceStore(InstaSearchPlugin.getDefault().getPreferenceStore());
setDescription("");
}
/**
* Creates the field editors. Field editors are abstractions of
* the common GUI blocks needed to manipulate various types
* of preferences. Each field editor knows how to save and
* restore itself.
*/
@Override
public void createFieldEditors() {
String[] fileValues = new String[]{"5", "10", "15", "25", "50"};
addField(new ComboFieldEditor(PreferenceConstants.P_SHOWN_FILES_COUNT, "Shown results (initially)", getArrayOfPairs(fileValues), getFieldEditorParent()));
String[] lineValues = new String[]{"3", "4", "5", "7", "10", "15", "25"};
addField(new ComboFieldEditor(PreferenceConstants.P_SHOWN_LINES_COUNT, "Preview lines", getArrayOfPairs(lineValues), getFieldEditorParent()));
addBoolField(PreferenceConstants.P_SHOW_MATCH_COUNT, "Show number of matches");
addBoolField(PreferenceConstants.P_SHOW_FULL_PATH, "Show full file path in results");
addBoolField(PreferenceConstants.P_DIALOG_ON_SHORTCUT, "Open search dialog with shortcut key (Ctrl+Alt+I)");
StringButtonFieldEditor extensions = new ExtensionsFieldEditor(getFieldEditorParent());
extensions.setChangeButtonText("...");
extensions.setEmptyStringAllowed(true);
addField(extensions);
addBoolField(PreferenceConstants.P_INDEX_EMPTY_EXTENSION, "Index files without extension");
BooleanFieldEditor indexJars = new BooleanFieldEditor(PreferenceConstants.P_INDEX_ARCHIVES, "Index JAR Source Attachements (beta, requires to re-build the index after enabling)", getFieldEditorParent());
addField(indexJars);
indexJars.setEnabled(false, getFieldEditorParent());
if( InstaSearchPlugin.getInstaSearch() != null && InstaSearchPlugin.getInstaSearch().getIndexer() instanceof WorkspaceIndexerJDT )
indexJars.setEnabled(true, getFieldEditorParent());
addBoolField(PreferenceConstants.P_FUZZY_SEARCH_AUTO, "Find similar matches when no exact matches found");
String version = InstaSearchPlugin.getVersion();
addBoolField(PreferenceConstants.P_CHECK_UPDATES, "Notify about updates (ver. " + version + ")");
periodicReindexEnabled = addBoolField(PreferenceConstants.P_INDEX_UPDATE_ENABLED, "Enable Automatic-Reindex");
periodicReindexInterval = new IntegerFieldEditor(PreferenceConstants.P_INDEX_UPDATE_INTERVAL, "Automatic Reindex interval (ms)",
getFieldEditorParent());
periodicReindexInterval.setValidRange(0, Integer.MAX_VALUE);
addField(periodicReindexInterval);
addField(new WorkspacePathEditor(PreferenceConstants.P_EXCLUDE_DIRS, "Exclude folders from index", "Select folder to exclude from indexing", getFieldEditorParent()));
//new Label(getFieldEditorParent(), SWT.NONE).setText("Note: Folders with Derived flag are excluded");
Link annotationsLink = new Link(getFieldEditorParent(), SWT.NONE);
annotationsLink.setText("See <a>Annotations</a> to set Search Results highlight color");
annotationsLink.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e)
{
PreferencesUtil.createPreferenceDialogOn(getShell(), "org.eclipse.ui.editors.preferencePages.Annotations", null, null).open();
}
});
}
@Override
protected void initialize(){
super.initialize();
periodicReindexInterval.setEnabled(periodicReindexEnabled.getBooleanValue(), getFieldEditorParent());
}
@Override
public boolean performOk() {
return super.performOk();
}
@Override
protected Control createContents(Composite parent) {
Control contents = super.createContents(parent);
return contents;
}
/**
*
*/
private BooleanFieldEditor addBoolField(String id, String label)
{
BooleanFieldEditor field = new BooleanFieldEditor(id, label, getFieldEditorParent());
addField(field);
return field;
}
/* (non-Javadoc)
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
*/
public void init(IWorkbench workbench) {
}
@Override
public void propertyChange(PropertyChangeEvent event)
{
super.propertyChange(event);
if( event.getSource() instanceof FieldEditor )
{
FieldEditor field = (FieldEditor)event.getSource();
if (field == periodicReindexEnabled){
periodicReindexInterval.setEnabled(periodicReindexEnabled.getBooleanValue(), getFieldEditorParent());
}
if( PreferenceConstants.P_INDEXABLE_EXTENSIONS.equals(field.getPreferenceName())
|| PreferenceConstants.P_EXCLUDE_DIRS.equals(field.getPreferenceName())
|| PreferenceConstants.P_INDEX_EMPTY_EXTENSION.equals(field.getPreferenceName()))
setMessage("Rebuilding of index is recommended", INFORMATION);
else if( PreferenceConstants.P_INDEX_ARCHIVES.equals(field.getPreferenceName()) )
setMessage("Rebuilding of index is required", INFORMATION);
}
}
@Override
protected void checkState()
{
super.checkState();
setValid(true);
}
private static String[][] getArrayOfPairs(String[] values)
{
String[][] pairs = new String[values.length][2];
for(int i = 0; i < values.length; i++) {
String val = values[i];
pairs[i] = new String[]{val, val};
}
return pairs;
}
private static class WorkspacePathEditor extends PathEditor
{
public WorkspacePathEditor(String name, String labelText, String dirChooserLabelText, Composite parent)
{
super(name, labelText, dirChooserLabelText, parent);
}
@Override
protected String getNewInputObject()
{
FilteredResourcesPatternDialog dlg = new FilteredResourcesPatternDialog(getShell());
dlg.setTitle("Exclude folders");
dlg.setMessage("Exclude folders matching pattern (? = any character, * = any string, ** = any subfolder)");
dlg.setInitialPattern("**/bin");
dlg.setHelpAvailable(false);
dlg.open();
if( dlg.getReturnCode() == Window.OK )
return dlg.getLastPattern();
return null;
};
}
private static class FilteredResourcesPatternDialog extends FilteredResourcesSelectionDialog
{
private String lastPattern = null;
private Pattern regexPattern;
/**
*/
public FilteredResourcesPatternDialog(Shell shell)
{
super(shell, false, ResourcesPlugin.getWorkspace().getRoot(), IResource.FOLDER | IResource.PROJECT );
}
@Override
protected ItemsFilter createFilter()
{
Text patternText = (Text) getPatternControl();
String wcPattern = patternText.getText();
if( wcPattern.startsWith("/") ) wcPattern = wcPattern.substring(1);
try
{
this.regexPattern = WorkspaceIndexer.wildcardToRegex(wcPattern);
} catch(Exception t)
{
InstaSearchPlugin.log(t);
return null; // invalid pattern, no filter
}
lastPattern = wcPattern;
ResourceFilter filter = new ResourceFilter()
{
@Override
public boolean isSubFilter(ItemsFilter filter)
{
return false;
}
@Override
public boolean matchItem(Object item)
{
if( !(item instanceof IResource) )
return false;
IResource resource = (IResource) item;
if( resource.getType() != IResource.FOLDER
&& resource.getType() != IResource.PROJECT )
return false;
if( resource.isDerived() )
return false;
String path = resource.getFullPath().toString();
if( path.startsWith("/") ) path = path.substring(1);
boolean matches = false;
try
{
matches = regexPattern.matcher(path).matches();
} catch(Exception t)
{
InstaSearchPlugin.log(t);
}
return matches;
}
@Override
public boolean equalsFilter(ItemsFilter iFilter)
{
return false;
}
};
return filter;
}
/**
* @return the lastPattern
*/
public String getLastPattern()
{
return lastPattern;
}
}
private static class ExtensionsFieldEditor extends StringButtonFieldEditor {
public ExtensionsFieldEditor(Composite parent) {
super(PreferenceConstants.P_INDEXABLE_EXTENSIONS, "Extensions of files to index", parent);
}
@Override
protected String changePressed() {
String exts = this.getStringValue();
TypeFilteringDialog dialog = new TypeFilteringDialog(getPage().getShell(),
Arrays.asList(exts.split(",")));
dialog.open();
Object[] newSelectedTypes = dialog.getResult();
if( newSelectedTypes == null )
return null;
Arrays.sort(newSelectedTypes);
return StringUtils.join(newSelectedTypes, ",");
}
@Override
protected void doFillIntoGrid(Composite parent, int numColumns) {
super.doFillIntoGrid(parent, numColumns);
Text txt = getTextControl();
GridData gd = (GridData) txt.getLayoutData();
if( gd != null )
gd.widthHint = 250;
}
};
}