package ca.uvic.chisel.javasketch.ui.internal.search;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.ImageDescriptor;
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.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
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.ui.dialogs.ContainerCheckedTreeViewer;
import ca.uvic.chisel.javasketch.IProgramSketch;
import ca.uvic.chisel.javasketch.SketchPlugin;
import ca.uvic.chisel.javasketch.ui.internal.views.TraceNavigatorLabelProvider;
public class TraceSearchPage extends DialogPage implements ISearchPage {
public static final String ID ="ca.uvic.chisel.javasketch.page.search";
private static final String TRACE_SEARCH_SECTION = "trace_search";
private static final String TRACE_SEARCH_STRINGS = "search_strings";
private static final String TRACE_SEARCH_MASK = "search_mask";
private static final String TRACE_SEARCH_SCOPE = "search_scope";
private ISearchPageContainer container;
private Combo searchCombo;
private Button classesButton;
private Button methodsButton;
private Button activationsButton;
private Button propertiesButton;
private ContainerCheckedTreeViewer tracesViewer;
private Button caseSensitive;
public TraceSearchPage() {
}
public TraceSearchPage(String title) {
super(title);
}
public TraceSearchPage(String title, ImageDescriptor image) {
super(title, image);
}
@Override
public boolean performAction() {
int searchMask = getSearchMask();
LinkedList<IProgramSketch> scope = new LinkedList<IProgramSketch>();
for (Object o : tracesViewer.getCheckedElements()) {
if (o instanceof IProgramSketch) {
scope.add((IProgramSketch) o);
}
}
NewSearchUI.runQueryInBackground(new TraceSearchQuery(scope
.toArray(new IProgramSketch[scope.size()]), searchCombo.getText(),
searchMask));
return true;
}
/**
* @return
*/
private int getSearchMask() {
int searchMask = 0;
if (classesButton.getSelection()) {
searchMask = TraceSearchQuery.CLASSES;
}
if (methodsButton.getSelection()) {
searchMask = TraceSearchQuery.METHODS;
}
if (activationsButton.getSelection()) {
searchMask |= TraceSearchQuery.ACTIVATIONS;
}
if (propertiesButton.getSelection()) {
searchMask = TraceSearchQuery.PROPERTIES;
}
if (caseSensitive.getSelection()) {
searchMask |= TraceSearchQuery.CASE_SENSITIVE;
}
return searchMask;
}
@Override
public void setContainer(ISearchPageContainer container) {
this.container = container;
container.setPerformActionEnabled(false);
}
@Override
public void createControl(Composite parent) {
Composite page = new Composite(parent, SWT.BORDER);
page.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
page.setLayout(new GridLayout());
createSearchArea(page);
createTypesArea(page);
createTracesArea(page);
setControl(page);
reload();
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)
*/
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
getControl().getParent().layout();
}
}
/**
* @param page
*/
private void createTracesArea(Composite page) {
Group tracesGroup = new Group(page, SWT.NONE);
tracesGroup.setLayout(new GridLayout());
tracesGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
tracesGroup.setText("Search Scope");
tracesViewer = new ContainerCheckedTreeViewer(tracesGroup, SWT.BORDER
| SWT.CHECK | SWT.DOUBLE_BUFFERED);
tracesViewer.setContentProvider(new SimpleTraceContentProvider());
tracesViewer.setLabelProvider(new TraceNavigatorLabelProvider());
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
// gd.heightHint = 300;
tracesViewer.getTree().setLayoutData(gd);
tracesViewer.setInput(ResourcesPlugin.getWorkspace().getRoot());
// treeCheckSelectionListener = new TreeCheckSelectionListener();
// tracesViewer.getTree().addSelectionListener(treeCheckSelectionListener);
tracesViewer.expandAll();
}
/**
* @param page
*/
private void createTypesArea(Composite page) {
Group typesGroup = new Group(page, SWT.NONE);
typesGroup.setText("Search For");
typesGroup.setLayout(new GridLayout(3, true));
GridDataFactory gdf = GridDataFactory.createFrom(new GridData(SWT.FILL,
SWT.FILL, true, false));
typesGroup.setLayoutData(gdf.create());
classesButton = new Button(typesGroup, SWT.RADIO);
classesButton.setText("Classes");
classesButton.setLayoutData(gdf.create());
methodsButton = new Button(typesGroup, SWT.RADIO);
methodsButton.setText("Methods");
methodsButton.setLayoutData(gdf.create());
activationsButton = new Button(typesGroup, SWT.CHECK);
activationsButton.setText("Include Activations");
activationsButton.setLayoutData(gdf.create());
SelectionListener enableListener = new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
activationsButton.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
};
methodsButton.addSelectionListener(enableListener);
classesButton.addSelectionListener(enableListener);
propertiesButton = new Button(typesGroup, SWT.RADIO);
propertiesButton.setText("Notes");
propertiesButton.setLayoutData(gdf.create());
propertiesButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
@Override
public void widgetSelected(SelectionEvent e) {
activationsButton.setEnabled(false);
}
});
}
/**
* @param page
*/
private void createSearchArea(Composite page) {
Composite searchArea = new Composite(page, SWT.NONE);
searchArea.setLayout(new GridLayout(2, false));
GridDataFactory gdf = GridDataFactory.createFrom(new GridData(SWT.FILL,
SWT.FILL, true, false));
GridData gd = gdf.create();
// gd.widthHint = convertWidthInCharsToPixels(200);
searchArea.setLayoutData(gd);
Label instructions = new Label(searchArea, SWT.NONE);
instructions
.setText("Search String (* = any string, ? = any character)");
gd = gdf.create();
gd.horizontalSpan = 2;
instructions.setLayoutData(gd);
searchCombo = new Combo(searchArea, SWT.BORDER);
gd = gdf.create();
gd.widthHint = convertWidthInCharsToPixels(50);
searchCombo.setLayoutData(gd);
searchCombo.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent e) {
if (searchCombo.getText() == null
|| searchCombo.getText().isEmpty()) {
setErrorMessage(null);
container.setPerformActionEnabled(false);
}
// make sure that no illegal characters are present
boolean ok = e.text.indexOf('%') < 0;
if (!ok) {
container.setPerformActionEnabled(false);
setErrorMessage("Illegal character: %");
} else {
setErrorMessage(null);
container.setPerformActionEnabled(true);
}
}
});
caseSensitive = new Button(searchArea, SWT.CHECK);
caseSensitive.setText("Case sensitive");
gd = gdf.create();
gd.grabExcessHorizontalSpace = false;
caseSensitive.setLayoutData(gd);
}
/**
*
*/
private void reload() {
IDialogSettings settings = SketchPlugin.getDefault()
.getDialogSettings();
IDialogSettings section = settings.getSection(TRACE_SEARCH_SECTION);
if (section == null) {
section = settings.addNewSection(TRACE_SEARCH_SECTION);
}
String[] searches = section.getArray(TRACE_SEARCH_STRINGS);
if (searches != null) {
if (searches.length > 0) {
searchCombo.setItems(searches);
searchCombo.setText(searches[0]);
}
}
try {
int mask = section.getInt(TRACE_SEARCH_MASK);
activationsButton
.setSelection((mask & TraceSearchQuery.ACTIVATIONS) != 0);
if ((mask & TraceSearchQuery.CLASSES) != 0) {
classesButton.setSelection(true);
activationsButton.setEnabled(true);
} else if ((mask & TraceSearchQuery.METHODS) != 0) {
methodsButton.setSelection(true);
activationsButton.setEnabled(true);
} else if ((mask & TraceSearchQuery.PROPERTIES) != 0) {
propertiesButton.setSelection(true);
activationsButton.setEnabled(false);
}
caseSensitive
.setSelection((mask & TraceSearchQuery.CASE_SENSITIVE) != 0);
} catch (NumberFormatException e) {
// there was no mask stored, set the activations button to
// selected
activationsButton.setSelection(true);
caseSensitive.setSelection(true);
}
String[] checked = section.getArray(TRACE_SEARCH_SCOPE);
if (checked != null) {
HashSet<IProgramSketch> checkedSketches = new HashSet<IProgramSketch>();
for (String id : checked) {
IProgramSketch sketch = SketchPlugin.getDefault().getSketch(id);
if (sketch != null) {
checkedSketches.add(sketch);
}
}
tracesViewer.setCheckedElements(checkedSketches.toArray());
}
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.DialogPage#dispose()
*/
@Override
public void dispose() {
writeConfiguration();
super.dispose();
}
/**
*
*/
private void writeConfiguration() {
IDialogSettings settings = SketchPlugin.getDefault()
.getDialogSettings();
IDialogSettings section = settings.getSection(TRACE_SEARCH_SECTION);
if (section == null) {
section = settings.addNewSection(TRACE_SEARCH_SECTION);
}
String[] searchStrings = section.getArray(TRACE_SEARCH_STRINGS);
if (searchStrings == null) {
searchStrings = new String[0];
}
LinkedList<String> searchList = new LinkedList<String>(Arrays
.asList(searchStrings));
for (Iterator<String> it = searchList.iterator(); it.hasNext();) {
String s = it.next();
if (s.equals(searchCombo.getText()) || s.isEmpty()) {
it.remove();
}
}
// remove the current search string from the list if it already
// exists.
LinkedList<String> newStrings = new LinkedList<String>();
String s = searchCombo.getText();
if (s != null && !s.isEmpty()) {
newStrings.add(s);
}
newStrings.addAll(searchList);
section.put(TRACE_SEARCH_STRINGS, newStrings
.toArray(new String[newStrings.size()]));
section.put(TRACE_SEARCH_MASK, getSearchMask());
ArrayList<String> scope = new ArrayList<String>();
for (Object o : tracesViewer.getCheckedElements()) {
if (o instanceof IProgramSketch) {
scope.add(((IProgramSketch) o).getID());
}
}
section
.put(TRACE_SEARCH_SCOPE, scope.toArray(new String[scope.size()]));
}
}