ext.org.eclipse.jdt.internal.ui.search.JavaSearchPage.java Source code

Java tutorial

Introduction

Here is the source code for ext.org.eclipse.jdt.internal.ui.search.JavaSearchPage.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2011 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 ext.org.eclipse.jdt.internal.ui.search;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

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.swt.widgets.Link;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;

import org.eclipse.core.resources.IFile;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;

import org.eclipse.jface.text.ITextSelection;

import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.IWorkbenchAdapter;

import org.eclipse.search.ui.ISearchPage;
import org.eclipse.search.ui.ISearchPageContainer;
import org.eclipse.search.ui.NewSearchUI;

import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IImportDeclaration;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.formatter.IndentManipulation;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.ui.search.ElementQuerySpecification;
import org.eclipse.jdt.ui.search.PatternQuerySpecification;
import org.eclipse.jdt.ui.search.QuerySpecification;

import patch.org.eclipse.jdt.internal.ui.JavaPlugin;

import ext.org.eclipse.jdt.internal.corext.util.Messages;
import ext.org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import ext.org.eclipse.jdt.internal.ui.actions.SelectionConverter;
import ext.org.eclipse.jdt.internal.ui.browsing.LogicalPackage;
import ext.org.eclipse.jdt.internal.ui.dialogs.TextFieldNavigationHandler;
import ext.org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import ext.org.eclipse.jdt.internal.ui.search.MatchLocations.MatchLocationSelectionDialog;
import ext.org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import ext.org.eclipse.jdt.internal.ui.util.SWTUtil;

public class JavaSearchPage extends DialogPage implements ISearchPage {

    private static class SearchPatternData {
        private final int searchFor;
        private final int limitTo;
        private final String pattern;
        private final boolean isCaseSensitive;
        private final int includeMask;
        private final int matchLocations;
        private final int scope;
        private final IWorkingSet[] workingSets;
        private IJavaElement javaElement;

        public SearchPatternData(int searchFor, int limitTo, int matchLocations, boolean isCaseSensitive,
                String pattern, IJavaElement element, int includeMask) {
            this(searchFor, limitTo, matchLocations, pattern, isCaseSensitive, element,
                    ISearchPageContainer.WORKSPACE_SCOPE, null, includeMask);
        }

        public SearchPatternData(int searchFor, int limitTo, int matchLocations, String pattern,
                boolean isCaseSensitive, IJavaElement element, int scope, IWorkingSet[] workingSets,
                int includeMask) {
            this.searchFor = searchFor;
            this.limitTo = limitTo;
            this.matchLocations = matchLocations;
            this.pattern = pattern;
            this.isCaseSensitive = isCaseSensitive;
            this.scope = scope;
            this.workingSets = workingSets;
            this.includeMask = includeMask;

            setJavaElement(element);
        }

        public void setJavaElement(IJavaElement javaElement) {
            this.javaElement = javaElement;
        }

        public boolean isCaseSensitive() {
            return isCaseSensitive;
        }

        public IJavaElement getJavaElement() {
            return javaElement;
        }

        public int getLimitTo() {
            return limitTo;
        }

        public String getPattern() {
            return pattern;
        }

        public int getScope() {
            return scope;
        }

        public int getSearchFor() {
            return searchFor;
        }

        public IWorkingSet[] getWorkingSets() {
            return workingSets;
        }

        public int getIncludeMask() {
            return includeMask;
        }

        public int getMatchLocations() {
            return matchLocations;
        }

        public void store(IDialogSettings settings) {
            settings.put("searchFor", searchFor); //$NON-NLS-1$
            settings.put("scope", scope); //$NON-NLS-1$
            settings.put("pattern", pattern); //$NON-NLS-1$
            settings.put("limitTo", limitTo); //$NON-NLS-1$
            settings.put("matchLocations", matchLocations); //$NON-NLS-1$
            settings.put("javaElement", javaElement != null ? javaElement.getHandleIdentifier() : ""); //$NON-NLS-1$ //$NON-NLS-2$
            settings.put("isCaseSensitive", isCaseSensitive); //$NON-NLS-1$
            if (workingSets != null) {
                String[] wsIds = new String[workingSets.length];
                for (int i = 0; i < workingSets.length; i++) {
                    wsIds[i] = workingSets[i].getName();
                }
                settings.put("workingSets", wsIds); //$NON-NLS-1$
            } else {
                settings.put("workingSets", new String[0]); //$NON-NLS-1$
            }
            settings.put("includeMask", includeMask); //$NON-NLS-1$
        }

        public static SearchPatternData create(IDialogSettings settings) {
            String pattern = settings.get("pattern"); //$NON-NLS-1$
            if (pattern.length() == 0) {
                return null;
            }
            IJavaElement elem = null;
            String handleId = settings.get("javaElement"); //$NON-NLS-1$
            if (handleId != null && handleId.length() > 0) {
                IJavaElement restored = JavaCore.create(handleId);
                if (restored != null && isSearchableType(restored) && restored.exists()) {
                    elem = restored;
                }
            }
            String[] wsIds = settings.getArray("workingSets"); //$NON-NLS-1$
            IWorkingSet[] workingSets = null;
            if (wsIds != null && wsIds.length > 0) {
                IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
                workingSets = new IWorkingSet[wsIds.length];
                for (int i = 0; workingSets != null && i < wsIds.length; i++) {
                    workingSets[i] = workingSetManager.getWorkingSet(wsIds[i]);
                    if (workingSets[i] == null) {
                        workingSets = null;
                    }
                }
            }

            try {
                int searchFor = settings.getInt("searchFor"); //$NON-NLS-1$
                int scope = settings.getInt("scope"); //$NON-NLS-1$
                int limitTo = settings.getInt("limitTo"); //$NON-NLS-1$

                int matchLocations = 0;
                if (settings.get("matchLocations") != null) { //$NON-NLS-1$
                    matchLocations = settings.getInt("matchLocations"); //$NON-NLS-1$
                }

                boolean isCaseSensitive = settings.getBoolean("isCaseSensitive"); //$NON-NLS-1$

                int includeMask;
                if (settings.get("includeMask") != null) { //$NON-NLS-1$
                    includeMask = settings.getInt("includeMask"); //$NON-NLS-1$
                } else {
                    includeMask = JavaSearchScopeFactory.NO_JRE;
                    if (settings.get("includeJRE") == null ? forceIncludeAll(limitTo, elem) //$NON-NLS-1$
                            : settings.getBoolean("includeJRE")) { //$NON-NLS-1$
                        includeMask = JavaSearchScopeFactory.ALL;
                    }
                }
                return new SearchPatternData(searchFor, limitTo, matchLocations, pattern, isCaseSensitive, elem,
                        scope, workingSets, includeMask);
            } catch (NumberFormatException e) {
                return null;
            }
        }

    }

    // search for
    private final static int TYPE = IJavaSearchConstants.TYPE;
    private final static int METHOD = IJavaSearchConstants.METHOD;
    private final static int PACKAGE = IJavaSearchConstants.PACKAGE;
    private final static int CONSTRUCTOR = IJavaSearchConstants.CONSTRUCTOR;
    private final static int FIELD = IJavaSearchConstants.FIELD;

    // limit to
    private final static int DECLARATIONS = IJavaSearchConstants.DECLARATIONS;
    private final static int IMPLEMENTORS = IJavaSearchConstants.IMPLEMENTORS;
    private final static int REFERENCES = IJavaSearchConstants.REFERENCES;
    private final static int SPECIFIC_REFERENCES = IJavaSearchConstants.CAST_TYPE_REFERENCE;
    private final static int ALL_OCCURRENCES = IJavaSearchConstants.ALL_OCCURRENCES;
    private final static int READ_ACCESSES = IJavaSearchConstants.READ_ACCESSES;
    private final static int WRITE_ACCESSES = IJavaSearchConstants.WRITE_ACCESSES;

    public static final String PARTICIPANT_EXTENSION_POINT = "org.eclipse.jdt.ui.queryParticipants"; //$NON-NLS-1$

    public static final String EXTENSION_POINT_ID = "org.eclipse.jdt.ui.JavaSearchPage"; //$NON-NLS-1$

    private static final int HISTORY_SIZE = 12;

    // Dialog store id constants
    private final static String PAGE_NAME = "JavaSearchPage"; //$NON-NLS-1$
    private final static String STORE_CASE_SENSITIVE = "CASE_SENSITIVE"; //$NON-NLS-1$
    private final static String STORE_INCLUDE_MASK = "INCLUDE_MASK"; //$NON-NLS-1$
    private final static String STORE_HISTORY = "HISTORY"; //$NON-NLS-1$
    private final static String STORE_HISTORY_SIZE = "HISTORY_SIZE"; //$NON-NLS-1$

    private final List<SearchPatternData> fPreviousSearchPatterns;

    private SearchPatternData fInitialData;
    private IJavaElement fJavaElement;
    private boolean fFirstTime = true;
    private IDialogSettings fDialogSettings;
    private boolean fIsCaseSensitive;

    private Combo fPattern;
    private ISearchPageContainer fContainer;
    private Button fCaseSensitive;

    private Button[] fSearchFor;
    private Button[] fLimitTo;
    private Button[] fIncludeMasks;
    private Group fLimitToGroup;

    private int fMatchLocations;
    private Link fMatchLocationsLink;

    /**
     *
     */
    public JavaSearchPage() {
        fPreviousSearchPatterns = new ArrayList<SearchPatternData>();
    }

    //---- Action Handling ------------------------------------------------

    public boolean performAction() {
        return performNewSearch();
    }

    private boolean performNewSearch() {
        SearchPatternData data = getPatternData();

        // Setup search scope
        IJavaSearchScope scope = null;
        String scopeDescription = ""; //$NON-NLS-1$

        int searchFor = data.getSearchFor();
        int limitTo = data.getLimitTo();
        if (limitTo == SPECIFIC_REFERENCES) {
            limitTo = fMatchLocations;
        }

        int includeMask = data.getIncludeMask();
        JavaSearchScopeFactory factory = JavaSearchScopeFactory.getInstance();

        switch (getContainer().getSelectedScope()) {
        case ISearchPageContainer.WORKSPACE_SCOPE:
            scopeDescription = factory.getWorkspaceScopeDescription(includeMask);
            scope = factory.createWorkspaceScope(includeMask);
            break;
        case ISearchPageContainer.SELECTION_SCOPE:
            IJavaElement[] javaElements = new IJavaElement[0];
            if (getContainer().getActiveEditorInput() != null) {
                IFile file = (IFile) getContainer().getActiveEditorInput().getAdapter(IFile.class);
                if (file != null && file.exists())
                    javaElements = new IJavaElement[] { JavaCore.create(file) };
            } else
                javaElements = factory.getJavaElements(getContainer().getSelection());
            scope = factory.createJavaSearchScope(javaElements, includeMask);
            scopeDescription = factory.getSelectionScopeDescription(javaElements, includeMask);
            break;
        case ISearchPageContainer.SELECTED_PROJECTS_SCOPE: {
            String[] projectNames = getContainer().getSelectedProjectNames();
            scope = factory.createJavaProjectSearchScope(projectNames, includeMask);
            scopeDescription = factory.getProjectScopeDescription(projectNames, includeMask);
            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 = factory.getWorkingSetScopeDescription(workingSets, includeMask);
            scope = factory.createJavaSearchScope(workingSets, includeMask);
            SearchUtil.updateLRUWorkingSets(workingSets);
        }
        }

        QuerySpecification querySpec = null;
        if (data.getJavaElement() != null && getPattern().equals(fInitialData.getPattern())) {
            if (limitTo == REFERENCES)
                SearchUtil.warnIfBinaryConstant(data.getJavaElement(), getShell());
            querySpec = new ElementQuerySpecification(data.getJavaElement(), limitTo, scope, scopeDescription);
        } else {
            querySpec = new PatternQuerySpecification(data.getPattern(), searchFor, data.isCaseSensitive(), limitTo,
                    scope, scopeDescription);
            data.setJavaElement(null);
        }

        JavaSearchQuery textSearchJob = new JavaSearchQuery(querySpec);
        NewSearchUI.runQueryInBackground(textSearchJob);
        return true;
    }

    private int getLimitTo() {
        for (int i = 0; i < fLimitTo.length; i++) {
            Button button = fLimitTo[i];
            if (button.getSelection()) {
                return getIntData(button);
            }
        }
        return -1;
    }

    private int setLimitTo(int searchFor, int limitTo) {
        if (searchFor != TYPE && limitTo == IMPLEMENTORS) {
            limitTo = REFERENCES;
        }

        if (searchFor != FIELD && (limitTo == READ_ACCESSES || limitTo == WRITE_ACCESSES)) {
            limitTo = REFERENCES;
        }

        if (searchFor != TYPE /*&& searchFor != FIELD*/ && searchFor != METHOD && limitTo == SPECIFIC_REFERENCES) {
            limitTo = REFERENCES;
        }
        fillLimitToGroup(searchFor, limitTo);
        return limitTo;
    }

    private int getIncludeMask() {
        int mask = 0;
        for (int i = 0; i < fIncludeMasks.length; i++) {
            Button button = fIncludeMasks[i];
            if (button.getSelection()) {
                mask |= getIntData(button);
            }
        }
        return mask;
    }

    private void setIncludeMask(int includeMask) {
        for (int i = 0; i < fIncludeMasks.length; i++) {
            Button button = fIncludeMasks[i];
            button.setSelection((includeMask & getIntData(button)) != 0);
        }
    }

    private void setMatchLocations(int matchLocations) {
        fMatchLocations = matchLocations;
        updateMatchLocationText();
    }

    private String[] getPreviousSearchPatterns() {
        // Search results are not persistent
        int patternCount = fPreviousSearchPatterns.size();
        String[] patterns = new String[patternCount];
        for (int i = 0; i < patternCount; i++)
            patterns[i] = fPreviousSearchPatterns.get(i).getPattern();
        return patterns;
    }

    private int getSearchFor() {
        for (int i = 0; i < fSearchFor.length; i++) {
            Button button = fSearchFor[i];
            if (button.getSelection()) {
                return getIntData(button);
            }
        }
        Assert.isTrue(false, "shouldNeverHappen"); //$NON-NLS-1$
        return -1;
    }

    private void setSearchFor(int searchFor) {
        for (int i = 0; i < fSearchFor.length; i++) {
            Button button = fSearchFor[i];
            button.setSelection(searchFor == getIntData(button));
        }
    }

    private int getIntData(Button button) {
        return ((Integer) button.getData()).intValue();
    }

    private String getPattern() {
        return fPattern.getText();
    }

    private SearchPatternData findInPrevious(String pattern) {
        for (Iterator<SearchPatternData> iter = fPreviousSearchPatterns.iterator(); iter.hasNext();) {
            SearchPatternData element = iter.next();
            if (pattern.equals(element.getPattern())) {
                return element;
            }
        }
        return null;
    }

    /**
     * Return search pattern data and update previous searches.
     * An existing entry will be updated.
     * @return the pattern data
     */
    private SearchPatternData getPatternData() {
        String pattern = getPattern();
        SearchPatternData match = findInPrevious(pattern);
        if (match != null) {
            fPreviousSearchPatterns.remove(match);
        }
        match = new SearchPatternData(getSearchFor(), getLimitTo(), fMatchLocations, pattern,
                fCaseSensitive.getSelection(), fJavaElement, getContainer().getSelectedScope(),
                getContainer().getSelectedWorkingSets(), getIncludeMask());

        fPreviousSearchPatterns.add(0, match); // insert on top
        return match;
    }

    /*
     * Implements method from IDialogPage
     */
    @Override
    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();
        }
        updateOKStatus();

        IEditorInput editorInput = getContainer().getActiveEditorInput();
        getContainer().setActiveEditorCanProvideScopeSelection(
                editorInput != null && editorInput.getAdapter(IFile.class) != null);

        super.setVisible(visible);
    }

    public boolean isValid() {
        return true;
    }

    //---- Widget creation ------------------------------------------------

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        initializeDialogUnits(parent);
        readConfiguration();

        Composite result = new Composite(parent, SWT.NONE);

        GridLayout layout = new GridLayout(2, true);
        layout.horizontalSpacing = 10;
        result.setLayout(layout);

        Control expressionComposite = createExpression(result);
        expressionComposite.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, true, false, 2, 1));

        Label separator = new Label(result, SWT.NONE);
        separator.setVisible(false);
        GridData data = new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1);
        data.heightHint = convertHeightInCharsToPixels(1) / 3;
        separator.setLayoutData(data);

        Control searchFor = createSearchFor(result);
        searchFor.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1));

        Control limitTo = createLimitTo(result);
        limitTo.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1));

        Control includeMask = createIncludeMask(result);
        includeMask.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1));

        //createParticipants(result);

        SelectionAdapter javaElementInitializer = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                if (getSearchFor() == fInitialData.getSearchFor())
                    fJavaElement = fInitialData.getJavaElement();
                else
                    fJavaElement = null;
                setLimitTo(getSearchFor(), getLimitTo());
                setIncludeMask(getIncludeMask());
                doPatternModified();
            }
        };

        for (int i = 0; i < fSearchFor.length; i++) {
            fSearchFor[i].addSelectionListener(javaElementInitializer);
        }

        setControl(result);

        Dialog.applyDialogFont(result);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(result, IJavaHelpContextIds.JAVA_SEARCH_PAGE);
    }

    /*private Control createParticipants(Composite result) {
       if (!SearchParticipantsExtensionPoint.hasAnyParticipants())
     return new Composite(result, SWT.NULL);
       Button selectParticipants= new Button(result, SWT.PUSH);
       selectParticipants.setText(SearchMessages.getString("SearchPage.select_participants.label")); //$NON-NLS-1$
       GridData gd= new GridData();
       gd.verticalAlignment= GridData.VERTICAL_ALIGN_BEGINNING;
       gd.horizontalAlignment= GridData.HORIZONTAL_ALIGN_END;
       gd.grabExcessHorizontalSpace= false;
       gd.horizontalAlignment= GridData.END;
       gd.horizontalSpan= 2;
       selectParticipants.setLayoutData(gd);
       selectParticipants.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent e) {
        PreferencePageSupport.showPreferencePage(getShell(), "org.eclipse.jdt.ui.preferences.SearchParticipantsExtensionPoint", new SearchParticipantsExtensionPoint()); //$NON-NLS-1$
     }
        
       });
       return selectParticipants;
    }*/

    private Control createExpression(Composite parent) {
        Composite result = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout(2, false);
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        result.setLayout(layout);

        // Pattern text + info
        Label label = new Label(result, SWT.LEFT);
        label.setText(SearchMessages.SearchPage_expression_label);
        label.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 2, 1));

        // Pattern combo
        fPattern = new Combo(result, SWT.SINGLE | SWT.BORDER);
        SWTUtil.setDefaultVisibleItemCount(fPattern);
        fPattern.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                handlePatternSelected();
                updateOKStatus();
            }
        });
        fPattern.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                doPatternModified();
                updateOKStatus();

            }
        });
        TextFieldNavigationHandler.install(fPattern);
        GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1);
        data.widthHint = convertWidthInCharsToPixels(50);
        fPattern.setLayoutData(data);

        // Ignore case checkbox
        fCaseSensitive = new Button(result, SWT.CHECK);
        fCaseSensitive.setText(SearchMessages.SearchPage_expression_caseSensitive);
        fCaseSensitive.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                fIsCaseSensitive = fCaseSensitive.getSelection();
            }
        });
        fCaseSensitive.setLayoutData(new GridData(GridData.FILL, GridData.FILL, false, false, 1, 1));

        return result;
    }

    final void updateOKStatus() {
        boolean isValidPattern = isValidSearchPattern();
        boolean isValidMask = getIncludeMask() != 0;
        getContainer().setPerformActionEnabled(isValidPattern && isValidMask);
    }

    private boolean isValidSearchPattern() {
        if (getPattern().length() == 0) {
            return false;
        }
        if (fJavaElement != null) {
            return true;
        }
        return SearchPattern.createPattern(getPattern(), getSearchFor(), getLimitTo(),
                SearchPattern.R_EXACT_MATCH) != null;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.DialogPage#dispose()
     */
    @Override
    public void dispose() {
        writeConfiguration();
        super.dispose();
    }

    private void doPatternModified() {
        if (fInitialData != null && getPattern().equals(fInitialData.getPattern())
                && fInitialData.getJavaElement() != null && fInitialData.getSearchFor() == getSearchFor()) {
            fCaseSensitive.setEnabled(false);
            fCaseSensitive.setSelection(true);
            fJavaElement = fInitialData.getJavaElement();
        } else {
            fCaseSensitive.setEnabled(true);
            fCaseSensitive.setSelection(fIsCaseSensitive);
            fJavaElement = null;
        }
    }

    private void handlePatternSelected() {
        int selectionIndex = fPattern.getSelectionIndex();
        if (selectionIndex < 0 || selectionIndex >= fPreviousSearchPatterns.size())
            return;

        SearchPatternData initialData = fPreviousSearchPatterns.get(selectionIndex);

        setSearchFor(initialData.getSearchFor());
        setLimitTo(initialData.getSearchFor(), initialData.getLimitTo());
        setIncludeMask(initialData.getIncludeMask());
        setMatchLocations(initialData.getMatchLocations());

        fPattern.setText(initialData.getPattern());
        fIsCaseSensitive = initialData.isCaseSensitive();
        fJavaElement = initialData.getJavaElement();
        fCaseSensitive.setEnabled(fJavaElement == null);
        fCaseSensitive.setSelection(initialData.isCaseSensitive());

        if (initialData.getWorkingSets() != null)
            getContainer().setSelectedWorkingSets(initialData.getWorkingSets());
        else
            getContainer().setSelectedScope(initialData.getScope());

        fInitialData = initialData;
    }

    private Control createSearchFor(Composite parent) {
        Group result = new Group(parent, SWT.NONE);
        result.setText(SearchMessages.SearchPage_searchFor_label);
        result.setLayout(new GridLayout(2, true));

        fSearchFor = new Button[] {
                createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_type, TYPE, true),
                createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_method, METHOD, false),
                createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_package, PACKAGE, false),
                createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_constructor, CONSTRUCTOR,
                        false),
                createButton(result, SWT.RADIO, SearchMessages.SearchPage_searchFor_field, FIELD, false) };

        // Fill with dummy radio buttons
        Label filler = new Label(result, SWT.NONE);
        filler.setVisible(false);
        filler.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));

        return result;
    }

    private Control createLimitTo(Composite parent) {
        fLimitToGroup = new Group(parent, SWT.NONE);
        fLimitToGroup.setText(SearchMessages.SearchPage_limitTo_label);
        fLimitToGroup.setLayout(new GridLayout(2, false));

        fillLimitToGroup(TYPE, ALL_OCCURRENCES);

        return fLimitToGroup;
    }

    private void fillLimitToGroup(int searchFor, int limitTo) {
        Control[] children = fLimitToGroup.getChildren();
        for (int i = 0; i < children.length; i++) {
            children[i].dispose();
        }
        fMatchLocationsLink = null;

        ArrayList<Button> buttons = new ArrayList<Button>();
        buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_allOccurrences,
                ALL_OCCURRENCES, limitTo == ALL_OCCURRENCES));
        buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_declarations,
                DECLARATIONS, limitTo == DECLARATIONS));

        buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_references, REFERENCES,
                limitTo == REFERENCES));
        if (searchFor == TYPE) {
            buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_implementors,
                    IMPLEMENTORS, limitTo == IMPLEMENTORS));

            buttons.add(createMethodLocationRadio(limitTo == SPECIFIC_REFERENCES));
        }

        if (searchFor == FIELD) {
            buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_readReferences,
                    READ_ACCESSES, limitTo == READ_ACCESSES));
            buttons.add(createButton(fLimitToGroup, SWT.RADIO, SearchMessages.SearchPage_limitTo_writeReferences,
                    WRITE_ACCESSES, limitTo == WRITE_ACCESSES));

            //         buttons.add(createMethodLocationRadio(limitTo == SPECIFIC_REFERENCES));
        }

        if (searchFor == METHOD) {
            buttons.add(createMethodLocationRadio(limitTo == SPECIFIC_REFERENCES));
        }

        fLimitTo = buttons.toArray(new Button[buttons.size()]);

        SelectionAdapter listener = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                performLimitToSelectionChanged((Button) e.widget);
            }
        };
        for (int i = 0; i < fLimitTo.length; i++) {
            fLimitTo[i].addSelectionListener(listener);
        }
        Dialog.applyDialogFont(fLimitToGroup); // re-apply font as we disposed the previous widgets

        fLimitToGroup.layout();
        //      // searchFor == FIELD needs one more row than the others
        //      fLimitToGroup.getShell().layout(new Control[] { fLimitToGroup.getChildren()[0] });
    }

    private Button createMethodLocationRadio(boolean isSelected) {
        Composite specificComposite = new Composite(fLimitToGroup, SWT.NONE);
        specificComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
        GridLayout layout = new GridLayout(2, false);
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        layout.horizontalSpacing = 0;
        specificComposite.setLayout(layout);

        Button button = createButton(specificComposite, SWT.RADIO,
                SearchMessages.JavaSearchPage_match_locations_label, SPECIFIC_REFERENCES, isSelected);
        fMatchLocationsLink = new Link(specificComposite, SWT.NONE);
        fMatchLocationsLink.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
        fMatchLocationsLink.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetDefaultSelected(SelectionEvent e) {
                performConfigureMatchLocation();
            }

            @Override
            public void widgetSelected(SelectionEvent e) {
                performConfigureMatchLocation();
            }
        });
        updateMatchLocationText();

        return button;
    }

    private void updateMatchLocationText() {
        if (fMatchLocationsLink != null) {
            int searchFor = getSearchFor();
            int totNum = MatchLocations.getTotalNumberOfSettings(searchFor);
            int currNum = MatchLocations.getNumberOfSelectedSettings(fMatchLocations, searchFor);

            fMatchLocationsLink.setText(Messages.format(SearchMessages.JavaSearchPage_match_location_link_label,
                    new Object[] { new Integer(currNum), new Integer(totNum) }));
            fMatchLocationsLink.setToolTipText(SearchMessages.JavaSearchPage_match_location_link_label_tooltip);
        }
    }

    protected final void performLimitToSelectionChanged(Button button) {
        if (button.getSelection()) {
            for (int i = 0; i < fLimitTo.length; i++) {
                Button curr = fLimitTo[i];
                if (curr != button) {
                    curr.setSelection(false);
                }
            }
        }
        updateUseJRE();
    }

    protected final void performConfigureMatchLocation() {
        for (int i = 0; i < fLimitTo.length; i++) {
            Button curr = fLimitTo[i];
            curr.setSelection(getIntData(curr) == SPECIFIC_REFERENCES);
        }

        MatchLocationSelectionDialog locationSelectionDialog = new MatchLocationSelectionDialog(getShell(),
                fMatchLocations, getSearchFor());
        if (locationSelectionDialog.open() == Window.OK) {
            setMatchLocations(locationSelectionDialog.getCurrentSelection());
        }
    }

    private Control createIncludeMask(Composite parent) {
        Group result = new Group(parent, SWT.NONE);
        result.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
        result.setText(SearchMessages.SearchPage_searchIn_label);
        result.setLayout(new GridLayout(4, false));
        fIncludeMasks = new Button[] {
                createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_sources,
                        JavaSearchScopeFactory.SOURCES, true),
                createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_projects,
                        JavaSearchScopeFactory.PROJECTS, true),
                createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_jre, JavaSearchScopeFactory.JRE,
                        false),
                createButton(result, SWT.CHECK, SearchMessages.SearchPage_searchIn_libraries,
                        JavaSearchScopeFactory.LIBS, true), };

        SelectionAdapter listener = new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                updateOKStatus();
            }
        };
        for (int i = 0; i < fIncludeMasks.length; i++) {
            fIncludeMasks[i].addSelectionListener(listener);
        }

        return result;
    }

    private Button createButton(Composite parent, int style, String text, int data, boolean isSelected) {
        Button button = new Button(parent, style);
        button.setText(text);
        button.setData(new Integer(data));
        button.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
        button.setSelection(isSelected);
        return button;
    }

    private void initSelections() {
        ISelection sel = getContainer().getSelection();

        IWorkbenchPage activePage = JavaPlugin.getActivePage();
        if (activePage != null) {
            IWorkbenchPart activePart = activePage.getActivePart();
            if (activePart instanceof JavaEditor) {
                JavaEditor javaEditor = (JavaEditor) activePart;
                if (javaEditor.isBreadcrumbActive()) {
                    sel = javaEditor.getBreadcrumb().getSelectionProvider().getSelection();
                }
            }
        }

        SearchPatternData initData = null;

        if (sel instanceof IStructuredSelection) {
            initData = tryStructuredSelection((IStructuredSelection) sel);
        } else if (sel instanceof ITextSelection) {
            IEditorPart activeEditor = getActiveEditor();
            if (activeEditor instanceof JavaEditor) {
                try {
                    IJavaElement[] elements = SelectionConverter.codeResolve((JavaEditor) activeEditor);
                    if (elements != null && elements.length > 0) {
                        initData = determineInitValuesFrom(elements[0]);
                    }
                } catch (JavaModelException e) {
                    // ignore
                }
            }
            if (initData == null) {
                initData = trySimpleTextSelection((ITextSelection) sel);
            }
        }
        if (initData == null) {
            initData = getDefaultInitValues();
        }

        fInitialData = initData;
        fJavaElement = initData.getJavaElement();
        fCaseSensitive.setSelection(initData.isCaseSensitive());
        fCaseSensitive.setEnabled(fJavaElement == null);

        setSearchFor(initData.getSearchFor());
        setLimitTo(initData.getSearchFor(), initData.getLimitTo());
        setIncludeMask(initData.getIncludeMask());
        setMatchLocations(initData.getMatchLocations());

        fPattern.setText(initData.getPattern());
    }

    private void updateUseJRE() {
        setIncludeMask(getIncludeMask());
    }

    private static boolean forceIncludeAll(int limitTo, IJavaElement elem) {
        return elem != null && (limitTo == DECLARATIONS || limitTo == IMPLEMENTORS);
    }

    private SearchPatternData tryStructuredSelection(IStructuredSelection selection) {
        if (selection == null || selection.size() > 1)
            return null;

        Object o = selection.getFirstElement();
        SearchPatternData res = null;
        if (o instanceof IJavaElement) {
            res = determineInitValuesFrom((IJavaElement) o);
        } else if (o instanceof LogicalPackage) {
            LogicalPackage lp = (LogicalPackage) o;
            return new SearchPatternData(PACKAGE, REFERENCES, 0, fIsCaseSensitive, lp.getElementName(), null,
                    getLastIncludeMask());
        } else if (o instanceof IAdaptable) {
            IJavaElement element = (IJavaElement) ((IAdaptable) o).getAdapter(IJavaElement.class);
            if (element != null) {
                res = determineInitValuesFrom(element);
            }
        }
        if (res == null && o instanceof IAdaptable) {
            IWorkbenchAdapter adapter = (IWorkbenchAdapter) ((IAdaptable) o).getAdapter(IWorkbenchAdapter.class);
            if (adapter != null) {
                return new SearchPatternData(TYPE, REFERENCES, 0, fIsCaseSensitive, adapter.getLabel(o), null,
                        getLastIncludeMask());
            }
        }
        return res;
    }

    final static boolean isSearchableType(IJavaElement element) {
        switch (element.getElementType()) {
        case IJavaElement.PACKAGE_FRAGMENT:
        case IJavaElement.PACKAGE_DECLARATION:
        case IJavaElement.IMPORT_DECLARATION:
        case IJavaElement.TYPE:
        case IJavaElement.FIELD:
        case IJavaElement.METHOD:
            return true;
        }
        return false;
    }

    private SearchPatternData determineInitValuesFrom(IJavaElement element) {
        try {
            //JavaSearchScopeFactory factory= JavaSearchScopeFactory.getInstance();
            //boolean isInsideJRE= factory.isInsideJRE(element);
            int includeMask = getLastIncludeMask();

            switch (element.getElementType()) {
            case IJavaElement.PACKAGE_FRAGMENT:
            case IJavaElement.PACKAGE_DECLARATION:
                return new SearchPatternData(PACKAGE, REFERENCES, 0, true, element.getElementName(), element,
                        includeMask);
            case IJavaElement.IMPORT_DECLARATION: {
                IImportDeclaration declaration = (IImportDeclaration) element;
                if (declaration.isOnDemand()) {
                    String name = Signature.getQualifier(declaration.getElementName());
                    return new SearchPatternData(PACKAGE, DECLARATIONS, 0, true, name, element,
                            JavaSearchScopeFactory.ALL);
                }
                return new SearchPatternData(TYPE, DECLARATIONS, 0, true, element.getElementName(), element,
                        JavaSearchScopeFactory.ALL);
            }
            case IJavaElement.TYPE:
                return new SearchPatternData(TYPE, REFERENCES, 0, true,
                        PatternStrings.getTypeSignature((IType) element), element, includeMask);
            case IJavaElement.COMPILATION_UNIT: {
                IType mainType = ((ICompilationUnit) element).findPrimaryType();
                if (mainType != null) {
                    return new SearchPatternData(TYPE, REFERENCES, 0, true,
                            PatternStrings.getTypeSignature(mainType), mainType, includeMask);
                }
                break;
            }
            case IJavaElement.CLASS_FILE: {
                IType mainType = ((IClassFile) element).getType();
                if (mainType.exists()) {
                    return new SearchPatternData(TYPE, REFERENCES, 0, true,
                            PatternStrings.getTypeSignature(mainType), mainType, includeMask);
                }
                break;
            }
            case IJavaElement.FIELD:
                return new SearchPatternData(FIELD, REFERENCES, 0, true,
                        PatternStrings.getFieldSignature((IField) element), element, includeMask);
            case IJavaElement.METHOD:
                IMethod method = (IMethod) element;
                int searchFor = method.isConstructor() ? CONSTRUCTOR : METHOD;
                return new SearchPatternData(searchFor, REFERENCES, 0, true,
                        PatternStrings.getMethodSignature(method), element, includeMask);
            }

        } catch (JavaModelException e) {
            if (!e.isDoesNotExist()) {
                ExceptionHandler.handle(e, SearchMessages.Search_Error_javaElementAccess_title,
                        SearchMessages.Search_Error_javaElementAccess_message);
            }
            // element might not exist
        }
        return null;
    }

    private SearchPatternData trySimpleTextSelection(ITextSelection selection) {
        String selectedText = selection.getText();
        if (selectedText != null && selectedText.length() > 0) {
            int i = 0;
            while (i < selectedText.length() && !IndentManipulation.isLineDelimiterChar(selectedText.charAt(i))) {
                i++;
            }
            if (i > 0) {
                return new SearchPatternData(TYPE, REFERENCES, 0, fIsCaseSensitive, selectedText.substring(0, i),
                        null, JavaSearchScopeFactory.ALL);
            }
        }
        return null;
    }

    private SearchPatternData getDefaultInitValues() {
        if (!fPreviousSearchPatterns.isEmpty()) {
            return fPreviousSearchPatterns.get(0);
        }

        return new SearchPatternData(TYPE, REFERENCES, 0, fIsCaseSensitive, "", null, getLastIncludeMask()); //$NON-NLS-1$
    }

    private int getLastIncludeMask() {
        try {
            return getDialogSettings().getInt(STORE_INCLUDE_MASK);
        } catch (NumberFormatException e) {
            return JavaSearchScopeFactory.NO_JRE;
        }
    }

    /*
     * Implements method from ISearchPage
     */
    public void setContainer(ISearchPageContainer container) {
        fContainer = container;
    }

    /**
     * Returns the search page's container.
     * @return the search page container
     */
    private ISearchPageContainer getContainer() {
        return fContainer;
    }

    private IEditorPart getActiveEditor() {
        IWorkbenchPage activePage = JavaPlugin.getActivePage();
        if (activePage != null) {
            return activePage.getActiveEditor();
        }
        return null;
    }

    //--------------- Configuration handling --------------

    /**
     * Returns the page settings for this Java search page.
     *
     * @return the page settings to be used
     */
    private IDialogSettings getDialogSettings() {
        if (fDialogSettings == null) {
            fDialogSettings = JavaPlugin.getDefault().getDialogSettingsSection(PAGE_NAME);
        }
        return fDialogSettings;
    }

    /**
     * Initializes itself from the stored page settings.
     */
    private void readConfiguration() {
        IDialogSettings s = getDialogSettings();
        fIsCaseSensitive = s.getBoolean(STORE_CASE_SENSITIVE);

        try {
            int historySize = s.getInt(STORE_HISTORY_SIZE);
            for (int i = 0; i < historySize; i++) {
                IDialogSettings histSettings = s.getSection(STORE_HISTORY + i);
                if (histSettings != null) {
                    SearchPatternData data = SearchPatternData.create(histSettings);
                    if (data != null) {
                        fPreviousSearchPatterns.add(data);
                    }
                }
            }
        } catch (NumberFormatException e) {
            // ignore
        }
    }

    /**
     * Stores the current configuration in the dialog store.
     */
    private void writeConfiguration() {
        IDialogSettings s = getDialogSettings();
        s.put(STORE_CASE_SENSITIVE, fIsCaseSensitive);
        s.put(STORE_INCLUDE_MASK, getIncludeMask());

        int historySize = Math.min(fPreviousSearchPatterns.size(), HISTORY_SIZE);
        s.put(STORE_HISTORY_SIZE, historySize);
        for (int i = 0; i < historySize; i++) {
            IDialogSettings histSettings = s.addNewSection(STORE_HISTORY + i);
            SearchPatternData data = fPreviousSearchPatterns.get(i);
            data.store(histSettings);
        }
    }
}