com.vectrace.MercurialEclipse.search.MercurialTextSearchPage.java Source code

Java tutorial

Introduction

Here is the source code for com.vectrace.MercurialEclipse.search.MercurialTextSearchPage.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2009 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
 *     Juerg Billeter, juergbi@ethz.ch - 47136 Search view should show match objects
 *     Ulrich Etter, etteru@ethz.ch - 47136 Search view should show match objects
 *     Roman Fuchs, fuchsro@ethz.ch - 47136 Search view should show match objects
 *     Bastian Doetsch - adaptation for MercurialEclipse
 *     Andrei Loskutov - bug fixes
 *     Philip Graf - Fixed bugs which FindBugs found
 *******************************************************************************/
package com.vectrace.MercurialEclipse.search;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.regex.PatternSyntaxException;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.search.internal.core.text.PatternConstructor;
import org.eclipse.search.internal.ui.SearchMessages;
import org.eclipse.search.internal.ui.SearchPlugin;
import org.eclipse.search.internal.ui.util.FileTypeEditor;
import org.eclipse.search.internal.ui.util.SWTUtil;
import org.eclipse.search.ui.ISearchPage;
import org.eclipse.search.ui.ISearchPageContainer;
import org.eclipse.search.ui.ISearchQuery;
import org.eclipse.search.ui.NewSearchUI;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;

import com.vectrace.MercurialEclipse.ui.SWTWidgetHelper;
import com.vectrace.MercurialEclipse.utils.StringUtils;

@SuppressWarnings("restriction")
public class MercurialTextSearchPage extends DialogPage implements ISearchPage {

    private static final int HISTORY_SIZE = 12;
    public static final String EXTENSION_POINT_ID = "org.eclipse.search.internal.ui.text.TextSearchPage"; //$NON-NLS-1$

    private static final boolean IS_REGEX_SEARCH = true;

    // Dialog store id constants
    private static final String PAGE_NAME = "TextSearchPage"; //$NON-NLS-1$
    private static final String STORE_HISTORY = "HISTORY"; //$NON-NLS-1$
    private static final String STORE_HISTORY_SIZE = "HISTORY_SIZE"; //$NON-NLS-1$

    private final List<SearchPatternData> fPreviousSearchPatterns = new ArrayList<SearchPatternData>(20);

    private boolean fFirstTime = true;
    private Combo fPattern;
    private Combo fExtensions;
    private CLabel fStatusLabel;
    private ISearchPageContainer fContainer;
    private FileTypeEditor fFileTypeEditor;

    private ContentAssistCommandAdapter fPatterFieldContentAssist;
    private Button firstRevisionCheckbox;

    private static class SearchPatternData {
        public final boolean isCaseSensitive;
        public final boolean isRegExSearch;
        public final String textPattern;
        public final String[] fileNamePatterns;
        public final int scope;
        public final IWorkingSet[] workingSets;

        public SearchPatternData(String textPattern, boolean isCaseSensitive, boolean isRegExSearch,
                String[] fileNamePatterns, int scope, IWorkingSet[] workingSets) {
            Assert.isNotNull(fileNamePatterns);
            this.isCaseSensitive = isCaseSensitive;
            this.isRegExSearch = isRegExSearch;
            this.textPattern = textPattern;
            this.fileNamePatterns = fileNamePatterns;
            this.scope = scope;
            this.workingSets = workingSets; // can be null
        }

        public void store(IDialogSettings settings) {
            settings.put("ignoreCase", !isCaseSensitive); //$NON-NLS-1$
            settings.put("isRegExSearch", isRegExSearch); //$NON-NLS-1$
            settings.put("textPattern", textPattern); //$NON-NLS-1$
            settings.put("fileNamePatterns", fileNamePatterns); //$NON-NLS-1$
            settings.put("scope", scope); //$NON-NLS-1$
            if (workingSets != null) {
                String[] wsIds = new String[workingSets.length];
                for (int i = 0; i < workingSets.length; i++) {
                    wsIds[i] = workingSets[i].getLabel();
                }
                settings.put("workingSets", wsIds); //$NON-NLS-1$
            } else {
                settings.put("workingSets", new String[0]); //$NON-NLS-1$
            }

        }

        public static SearchPatternData create(IDialogSettings settings) {
            String textPattern = settings.get("textPattern"); //$NON-NLS-1$
            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;
                    }
                }
            }
            String[] fileNamePatterns = settings.getArray("fileNamePatterns"); //$NON-NLS-1$
            if (fileNamePatterns == null) {
                fileNamePatterns = new String[0];
            }
            try {
                int scope = settings.getInt("scope"); //$NON-NLS-1$
                boolean isRegExSearch = settings.getBoolean("isRegExSearch"); //$NON-NLS-1$
                boolean ignoreCase = settings.getBoolean("ignoreCase"); //$NON-NLS-1$

                return new SearchPatternData(textPattern, !ignoreCase, isRegExSearch, fileNamePatterns, scope,
                        workingSets);
            } catch (NumberFormatException e) {
                return null;
            }
        }

    }

    static class TextSearchPageInput {

        private final String fSearchText;
        private final MercurialTextSearchScope fScope;

        public TextSearchPageInput(String searchText, MercurialTextSearchScope scope) {
            fSearchText = searchText;
            fScope = scope;
        }

        public String getSearchText() {
            return fSearchText;
        }

        public MercurialTextSearchScope getScope() {
            return fScope;
        }
    }

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

    private ISearchQuery newQuery() {
        SearchPatternData data = getPatternData();
        TextSearchPageInput input = new TextSearchPageInput(data.textPattern, createTextSearchScope());
        return MercurialTextSearchQueryProvider.createQuery(input);
    }

    public boolean performAction() {
        NewSearchUI.runQueryInBackground(newQuery());
        return true;
    }

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

    public MercurialTextSearchScope createTextSearchScope() {
        // Setup search scope
        switch (getContainer().getSelectedScope()) {
        case ISearchPageContainer.WORKSPACE_SCOPE:
            return MercurialTextSearchScope.newWorkspaceScope(getExtensions(),
                    firstRevisionCheckbox.getSelection());
        case ISearchPageContainer.SELECTION_SCOPE:
            return getSelectedResourcesScope();
        case ISearchPageContainer.SELECTED_PROJECTS_SCOPE:
            return getEnclosingProjectScope();
        case ISearchPageContainer.WORKING_SET_SCOPE:
            IWorkingSet[] workingSets = getContainer().getSelectedWorkingSets();
            return MercurialTextSearchScope.newSearchScope(workingSets, getExtensions(),
                    firstRevisionCheckbox.getSelection());
        default:
            // unknown scope
            return MercurialTextSearchScope.newWorkspaceScope(getExtensions(),
                    firstRevisionCheckbox.getSelection());
        }
    }

    private MercurialTextSearchScope getSelectedResourcesScope() {
        HashSet<IResource> resources = new HashSet<IResource>();
        ISelection sel = getContainer().getSelection();
        if (sel instanceof IStructuredSelection && !sel.isEmpty()) {
            Iterator<?> iter = ((IStructuredSelection) sel).iterator();
            while (iter.hasNext()) {
                Object curr = iter.next();
                if (curr instanceof IWorkingSet) {
                    IWorkingSet workingSet = (IWorkingSet) curr;
                    if (workingSet.isAggregateWorkingSet() && workingSet.isEmpty()) {
                        return MercurialTextSearchScope.newWorkspaceScope(getExtensions(),
                                firstRevisionCheckbox.getSelection());
                    }
                    IAdaptable[] elements = workingSet.getElements();
                    for (int i = 0; i < elements.length; i++) {
                        IResource resource = (IResource) elements[i].getAdapter(IResource.class);
                        if (resource != null && resource.isAccessible()) {
                            resources.add(resource);
                        }
                    }
                } else if (curr instanceof IAdaptable) {
                    IResource resource = (IResource) ((IAdaptable) curr).getAdapter(IResource.class);
                    if (resource != null && resource.isAccessible()) {
                        resources.add(resource);
                    }
                }
            }
        }
        IResource[] arr = resources.toArray(new IResource[resources.size()]);
        return MercurialTextSearchScope.newSearchScope(arr, getExtensions(), firstRevisionCheckbox.getSelection());
    }

    private MercurialTextSearchScope getEnclosingProjectScope() {
        String[] enclosingProjectName = getContainer().getSelectedProjectNames();
        if (enclosingProjectName == null) {
            return MercurialTextSearchScope.newWorkspaceScope(getExtensions(),
                    firstRevisionCheckbox.getSelection());
        }

        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
        IResource[] res = new IResource[enclosingProjectName.length];
        for (int i = 0; i < res.length; i++) {
            res[i] = root.getProject(enclosingProjectName[i]);
        }

        return MercurialTextSearchScope.newSearchScope(res, getExtensions(), firstRevisionCheckbox.getSelection());
    }

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

    /**
     * Return search pattern data and update previous searches. An existing entry will be updated.
     *
     * @return the search pattern data
     */
    private SearchPatternData getPatternData() {
        SearchPatternData match = findInPrevious(fPattern.getText());
        if (match != null) {
            fPreviousSearchPatterns.remove(match);
        }
        match = new SearchPatternData(getPattern(), false, IS_REGEX_SEARCH, getExtensions(),
                getContainer().getSelectedScope(), getContainer().getSelectedWorkingSets());
        fPreviousSearchPatterns.add(0, match);
        return match;
    }

    private String[] getPreviousExtensions() {
        List<String> extensions = new ArrayList<String>(fPreviousSearchPatterns.size());
        int size = fPreviousSearchPatterns.size();
        for (int i = 0; i < size; i++) {
            SearchPatternData data = fPreviousSearchPatterns.get(i);
            String text = FileTypeEditor.typesToString(data.fileNamePatterns);
            if (!extensions.contains(text)) {
                extensions.add(text);
            }
        }
        return extensions.toArray(new String[extensions.size()]);
    }

    private String[] getPreviousSearchPatterns() {
        int size = fPreviousSearchPatterns.size();
        String[] patterns = new String[size];
        for (int i = 0; i < size; i++) {
            patterns[i] = (fPreviousSearchPatterns.get(i)).textPattern;
        }
        return patterns;
    }

    private String[] getExtensions() {
        return fFileTypeEditor.getFileTypes();
    }

    @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());
                fExtensions.setItems(getPreviousExtensions());
                // if (fExtensions.getItemCount() == 0) {
                // loadFilePatternDefaults();
                // }
                if (!initializePatternControl()) {
                    fPattern.select(0);
                    fExtensions.setText("*"); //$NON-NLS-1$
                    handleWidgetSelected();
                }
            }
            fPattern.setFocus();
        }
        updateOKStatus();
        super.setVisible(visible);
    }

    final void updateOKStatus() {
        boolean regexStatus = validateRegex();
        boolean hasFilePattern = fExtensions.getText().length() > 0;
        boolean hasTextPattern = fPattern.getText().length() > 0;
        getContainer().setPerformActionEnabled(regexStatus && hasFilePattern && hasTextPattern);
    }

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

    public void createControl(Composite parent) {
        initializeDialogUnits(parent);
        readConfiguration();

        Composite result = new Composite(parent, SWT.NONE);
        result.setFont(parent.getFont());
        GridLayout layout = new GridLayout(2, false);
        result.setLayout(layout);

        addTextPatternControls(result);

        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);

        addFileNameControls(result);

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

        addSearchInControls(result);

        setControl(result);
        Dialog.applyDialogFont(result);
    }

    private void addSearchInControls(Composite result) {
        Group g = SWTWidgetHelper.createGroup(result, "Search in");
        this.firstRevisionCheckbox = SWTWidgetHelper.createCheckBox(g, "Search in all changesets");
        this.firstRevisionCheckbox.setEnabled(true);
        this.firstRevisionCheckbox.setSelection(false);
    }

    private boolean validateRegex() {
        if (IS_REGEX_SEARCH) {
            try {
                PatternConstructor.createPattern(fPattern.getText(), false, true);
            } catch (PatternSyntaxException e) {
                String locMessage = e.getLocalizedMessage();
                int i = 0;
                while (i < locMessage.length() && "\n\r".indexOf(locMessage.charAt(i)) == -1) { //$NON-NLS-1$
                    i++;
                }
                statusMessage(true, locMessage.substring(0, i)); // only take first line
                return false;
            }
            statusMessage(false, ""); //$NON-NLS-1$
        } else {
            statusMessage(false, SearchMessages.SearchPage_containingText_hint);
        }
        return true;
    }

    private void addTextPatternControls(Composite group) {
        // grid layout with 2 columns

        // Info text
        Label label = new Label(group, SWT.LEAD);
        label.setText(SearchMessages.SearchPage_containingText_text);
        label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
        label.setFont(group.getFont());

        // 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() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                handleWidgetSelected();
                updateOKStatus();
            }
        });
        // add some listeners for regex syntax checking
        fPattern.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                updateOKStatus();
            }
        });
        fPattern.setFont(group.getFont());
        GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1);
        data.widthHint = convertWidthInCharsToPixels(50);
        fPattern.setLayoutData(data);

        // Text line which explains the special characters
        fStatusLabel = new CLabel(group, SWT.LEAD);
        fStatusLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
        fStatusLabel.setFont(group.getFont());
        fStatusLabel.setAlignment(SWT.LEFT);
        fStatusLabel.setText(SearchMessages.SearchPage_containingText_hint);

        ComboContentAdapter contentAdapter = new ComboContentAdapter();
        FindReplaceDocumentAdapterContentProposalProvider findProposer = new FindReplaceDocumentAdapterContentProposalProvider(
                true);
        fPatterFieldContentAssist = new ContentAssistCommandAdapter(fPattern, contentAdapter, findProposer,
                ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, new char[] { '\\', '[', '(' }, true);
        fPatterFieldContentAssist.setEnabled(IS_REGEX_SEARCH);
    }

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

        SearchPatternData patternData = fPreviousSearchPatterns.get(selectionIndex);
        if (!fPattern.getText().equals(patternData.textPattern)) {
            return;
        }

        fPattern.setText(patternData.textPattern);
        fFileTypeEditor.setFileTypes(patternData.fileNamePatterns);
        if (patternData.workingSets != null) {
            getContainer().setSelectedWorkingSets(patternData.workingSets);
        } else {
            getContainer().setSelectedScope(patternData.scope);
        }
    }

    private boolean initializePatternControl() {
        ISelection selection = getSelection();
        if (selection instanceof ITextSelection && !selection.isEmpty()) {
            String text = ((ITextSelection) selection).getText();
            if (text != null) {
                if (IS_REGEX_SEARCH) {
                    fPattern.setText(escapeForRegExPattern(text));
                } else {
                    fPattern.setText(insertEscapeChars(text));
                }

                if (getPreviousExtensions().length > 0) {
                    fExtensions.setText(getPreviousExtensions()[0]);
                } else {
                    String extension = getExtensionFromEditor();
                    if (extension != null) {
                        fExtensions.setText(extension);
                    } else {
                        fExtensions.setText("*"); //$NON-NLS-1$
                    }
                }
                return true;
            }
        }
        return false;
    }

    /**
     * TODO this is a temporary copy from FindReplaceDocumentAdapter (Eclipse 3.5) we have to keep
     * it as long as we want to be Eclipse 3.4 compatible
     *
     * Escapes special characters in the string, such that the resulting pattern matches the given
     * string.
     *
     * @param string
     *            the string to escape
     * @return a regex pattern that matches the given string
     * @since 3.5
     */
    private static String escapeForRegExPattern(String string) {
        // implements https://bugs.eclipse.org/bugs/show_bug.cgi?id=44422

        StringBuffer pattern = new StringBuffer(string.length() + 16);
        int length = string.length();
        if (length > 0 && string.charAt(0) == '^') {
            pattern.append('\\');
        }
        for (int i = 0; i < length; i++) {
            char ch = string.charAt(i);
            switch (ch) {
            case '\\':
            case '(':
            case ')':
            case '[':
            case ']':
            case '{':
            case '}':
            case '.':
            case '?':
            case '*':
            case '+':
            case '|':
                pattern.append('\\').append(ch);
                break;

            case '\r':
                if (i + 1 < length && string.charAt(i + 1) == '\n') {
                    i++;
                }
                pattern.append("\\R"); //$NON-NLS-1$
                break;
            case '\n':
                pattern.append("\\R"); //$NON-NLS-1$
                break;
            case '\t':
                pattern.append("\\t"); //$NON-NLS-1$
                break;
            case '\f':
                pattern.append("\\f"); //$NON-NLS-1$
                break;
            case 0x07:
                pattern.append("\\a"); //$NON-NLS-1$
                break;
            case 0x1B:
                pattern.append("\\e"); //$NON-NLS-1$
                break;

            default:
                if (0 <= ch && ch < 0x20) {
                    pattern.append("\\x"); //$NON-NLS-1$
                    pattern.append(Integer.toHexString(ch).toUpperCase());
                } else {
                    pattern.append(ch);
                }
            }
        }
        if (length > 0 && string.charAt(length - 1) == '$') {
            pattern.insert(pattern.length() - 1, '\\');
        }
        return pattern.toString();
    }

    private static String insertEscapeChars(String text) {
        if (StringUtils.isEmpty(text)) {
            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++;
        }
        return sbOut.toString();
    }

    private static 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();
                }
                return "*." + extension; //$NON-NLS-1$
            }
        }
        return null;
    }

    private void addFileNameControls(Composite group) {
        // grid layout with 2 columns

        // Line with label, combo and button
        Label label = new Label(group, SWT.LEAD);
        label.setText(SearchMessages.SearchPage_fileNamePatterns_text);
        label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
        label.setFont(group.getFont());

        fExtensions = new Combo(group, SWT.SINGLE | SWT.BORDER);
        fExtensions.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                updateOKStatus();
            }
        });
        GridData data = new GridData(GridData.FILL, GridData.FILL, true, false, 1, 1);
        data.widthHint = convertWidthInCharsToPixels(50);
        fExtensions.setLayoutData(data);
        fExtensions.setFont(group.getFont());

        Button button = new Button(group, SWT.PUSH);
        button.setText(SearchMessages.SearchPage_browse);
        GridData gridData = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1);
        gridData.widthHint = SWTUtil.getButtonWidthHint(button);
        button.setLayoutData(gridData);
        button.setFont(group.getFont());

        fFileTypeEditor = new FileTypeEditor(fExtensions, button);

        // Text line which explains the special characters
        Label description = new Label(group, SWT.LEAD);
        description.setText(SearchMessages.SearchPage_fileNamePatterns_hint);
        description.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
        description.setFont(group.getFont());
    }

    /**
     * Sets the search page's container.
     *
     * @param container
     *            the container to set
     */
    public void setContainer(ISearchPageContainer container) {
        fContainer = container;
    }

    private ISearchPageContainer getContainer() {
        return fContainer;
    }

    private ISelection getSelection() {
        return fContainer.getSelection();
    }

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

    @Override
    public void dispose() {
        writeConfiguration();
        super.dispose();
    }

    /**
     * Returns the page settings for this Text search page.
     *
     * @return the page settings to be used
     */
    private static IDialogSettings getDialogSettings() {
        return SearchPlugin.getDefault().getDialogSettingsSection(PAGE_NAME);
    }

    /**
     * Initializes itself from the stored page settings.
     */
    private void readConfiguration() {
        IDialogSettings s = getDialogSettings();
        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 it current configuration in the dialog store.
     */
    private void writeConfiguration() {
        IDialogSettings s = getDialogSettings();

        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);
        }
    }

    private void statusMessage(boolean error, String message) {
        fStatusLabel.setText(message);
        if (error) {
            fStatusLabel.setForeground(JFaceColors.getErrorText(fStatusLabel.getDisplay()));
        } else {
            fStatusLabel.setForeground(null);
        }
    }

}