com.xored.glance.ui.panels.SearchPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.xored.glance.ui.panels.SearchPanel.java

Source

/*******************************************************************************
 * Copyright (c) 2008 xored software, Inc. All rights reserved. This program and the accompanying
 * materials are made available under the terms of the Eclipse Public License v1.0 which accompanies
 * this distribution, and is available at http://www.eclipse.org/legal/epl-v10.html Contributors:
 * xored software, Inc. - initial API and Implementation (Yuri Strot)
 *******************************************************************************/
package com.xored.glance.ui.panels;

import com.xored.glance.internal.ui.GlanceEventDispatcher;
import com.xored.glance.internal.ui.GlancePlugin;
import com.xored.glance.internal.ui.panels.CheckAction;
import com.xored.glance.internal.ui.panels.ImageAnimation;
import com.xored.glance.internal.ui.preferences.IPreferenceConstants;
import com.xored.glance.internal.ui.search.SearchManager;
import com.xored.glance.internal.ui.search.SearchRule;
import com.xored.glance.ui.sources.Match;
import com.xored.glance.ui.utils.SelectionAdapter;
import com.xored.glance.ui.utils.UIUtils;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.PopupDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.texteditor.TextEditorPlugin;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Yuri Strot
 */
@SuppressWarnings("restriction")
public abstract class SearchPanel implements ISearchPanel, IPreferenceConstants, IPropertyChangeListener {

    class SearchSynchronizer {

        private IDialogSettings dialogSettings;
        private boolean wrapInit;
        private boolean caseInit;
        private boolean wholeWordInit;
        private boolean regExInit;
        private List<String> findHistory = new ArrayList<String>();
        private boolean incrementalInit;

        /**
         * Returns the dialog settings object used to share state between several find/replace dialogs.
         * 
         * @return the dialog settings to be used
         */
        private IDialogSettings getDialogSettings() {
            IDialogSettings settings = TextEditorPlugin.getDefault().getDialogSettings();
            dialogSettings = settings.getSection("org.eclipse.ui.texteditor.FindReplaceDialog");
            if (dialogSettings == null) {
                dialogSettings = settings.addNewSection("org.eclipse.ui.texteditor.FindReplaceDialog");
            }
            return dialogSettings;
        }

        private String getFindString() {
            if (title == null) {
                return null;
            }
            String findString = title.getText();
            findString = fixItem(findString);
            return findString;
        }

        /**
         * Initializes itself from the dialog settings with the same state as at the previous
         * invocation.
         */
        private void readConfiguration() {
            IDialogSettings s = getDialogSettings();

            wrapInit = s.get("wrap") == null || s.getBoolean("wrap"); //$NON-NLS-1$ //$NON-NLS-2$
            caseInit = s.getBoolean("casesensitive"); //$NON-NLS-1$
            wholeWordInit = s.getBoolean("wholeword"); //$NON-NLS-1$
            incrementalInit = s.getBoolean("incremental"); //$NON-NLS-1$
            regExInit = s.getBoolean("isRegEx"); //$NON-NLS-1$

            String[] findHistoryInit = s.getArray("findhistory"); //$NON-NLS-1$
            if (findHistoryInit != null) {
                findHistory.clear();
                for (int i = 0; i < findHistoryInit.length; i++) {
                    findHistory.add(findHistoryInit[i]);
                }
            }

            IPreferenceStore preferences = GlancePlugin.getDefault().getPreferenceStore();
            preferences.setValue(SEARCH_CASE_SENSITIVE, caseInit);
            preferences.setValue(SEARCH_REGEXP, regExInit);
            preferences.setValue(SEARCH_WORD_PREFIX, wholeWordInit);
        }

        /**
         * Stores its current configuration in the dialog store.
         */
        private void writeConfiguration() {
            String findString = getFindString();
            if (findString == null) {
                return;
            }
            IDialogSettings s = getDialogSettings();
            IPreferenceStore preferences = GlancePlugin.getDefault().getPreferenceStore();

            boolean caseSensitive = preferences.getBoolean(SEARCH_CASE_SENSITIVE);
            boolean regExp = preferences.getBoolean(SEARCH_REGEXP);
            boolean wordPrefix = preferences.getBoolean(SEARCH_WORD_PREFIX);

            s.put("wrap", wrapInit); //$NON-NLS-1$
            s.put("casesensitive", caseSensitive); //$NON-NLS-1$
            s.put("wholeword", wordPrefix); //$NON-NLS-1$
            s.put("incremental", incrementalInit); //$NON-NLS-1$
            s.put("isRegEx", regExp); //$NON-NLS-1$
            s.put("selection", ""); //$NON-NLS-1$ (original: fTarget.getSelectionText())

            if (!findHistory.isEmpty() && findString.equals(findHistory.get(0))) {
                return;
            }

            int index = findHistory.indexOf(findString);
            if (index != -1) {
                findHistory.remove(index);
            }
            findHistory.add(0, findString);

            while (findHistory.size() > 8) {
                findHistory.remove(8);
            }
            String[] names = new String[findHistory.size()];
            findHistory.toArray(names);
            s.put("findhistory", names); //$NON-NLS-1$
        }
    }

    private class UpdateInfoThread extends ImageAnimation {

        private volatile boolean stop = false;

        public UpdateInfoThread() throws CoreException {
            super(getWaitImageStream(), getWaitBGColor());
        }

        public void requestStop() {
            stop = true;
        }

        @Override
        protected boolean isTerminated() {
            return stop || indexState != INDEXING_STATE_IN_PROGRESS;
        }

        @Override
        protected void updateImage(final Image image) {
            updateInfo(image);
        }
    }

    protected static final Color GOOD_COLOR = Display.getDefault().getSystemColor(SWT.COLOR_WHITE);

    protected static final Color BAD_COLOR = new Color(Display.getDefault(), 255, 102, 102);

    private static URL getWaitImageStream() throws CoreException {
        URL url = FileLocator.find(GlancePlugin.getDefault().getBundle(), new Path(GlancePlugin.IMG_WAIT), null);
        try {
            url = FileLocator.resolve(url);
            return url;
        } catch (final IOException e) {
            throw new CoreException(GlancePlugin.createStatus("Can't find wait image", e));
        }
    }

    protected Composite container;

    protected Combo title;

    private boolean titleEnabled = true;

    private final ListenerList listeners = new ListenerList();

    private final ModifyListener modifyListener = new ModifyListener() {
        @Override
        public void modifyText(final ModifyEvent e) {
            textChanged();
        }
    };

    private List<String> findHistory;

    private boolean historyDirty = true;

    private ToolItem bNext;

    private ToolItem bPrev;

    private ToolItem bIndexing;

    private ToolBar toolBar;

    private SearchRule rule;

    private Match[] result = Match.EMPTY;

    private double indexState;

    private double indexPercent;

    private String taskName;

    private int preferredHeight;

    private int preferredWidth;

    private UpdateInfoThread updateInfoThread;

    private SearchSynchronizer searchSynchronizer;

    /**
     * @param parent
     * @param style
     */
    public SearchPanel() {
        rule = new SearchRule("");
        getPreferences().addPropertyChangeListener(this);
        searchSynchronizer = new SearchSynchronizer();
        searchSynchronizer.readConfiguration();
    }

    @Override
    public void addPanelListener(final ISearchPanelListener listener) {
        listeners.add(listener);
    }

    @Override
    public void allFound(final Match[] matches) {
        result = matches;
        UIUtils.asyncExec(title, new Runnable() {
            @Override
            public void run() {
                setBackground(result.length > 0);
            }
        });
    }

    @Override
    public void clearHistory() {
        if (title != null && !title.isDisposed()) {
            title.removeModifyListener(modifyListener);
            try {
                title.removeAll();
                findHistory.clear();
            } finally {
                title.addModifyListener(modifyListener);
                historyDirty = false;
            }
        }
    }

    public void createContent(final Composite parent) {
        final Composite container = createContainer(parent);
        final GridLayout layout = new GridLayout(3, false);
        layout.verticalSpacing = 0;
        layout.marginHeight = 0;
        layout.marginWidth = 0;
        container.setLayout(layout);
        createIcon(container);
        createText(container, SWT.BORDER);
        createToolBar(container);
        initSize(container);
    }

    @Override
    public void findNext() {
        updateHistory();
        final Object[] objects = listeners.getListeners();
        for (final Object object : objects) {
            final ISearchPanelListener listener = (ISearchPanelListener) object;
            listener.findNext();
        }
    }

    @Override
    public void findPrevious() {
        updateHistory();
        final Object[] objects = listeners.getListeners();
        for (final Object object : objects) {
            final ISearchPanelListener listener = (ISearchPanelListener) object;
            listener.findPrevious();
        }
    }

    @Override
    public void finished() {
        UIUtils.asyncExec(title, new Runnable() {
            @Override
            public void run() {
                if (title.getText().length() == 0) {
                    final Object[] objects = listeners.getListeners();
                    for (final Object object : objects) {
                        final ISearchPanelListener listener = (ISearchPanelListener) object;
                        listener.clearStatus();
                    }
                }
            }
        });
    }

    @Override
    public void firstFound(final Match match) {
        UIUtils.asyncExec(title, new Runnable() {
            @Override
            public void run() {
                setBackground(match != null);
            }
        });
    }

    @Override
    public Control getControl() {
        return container;
    }

    /**
     * @return the rule
     */
    @Override
    public SearchRule getRule() {
        return rule;
    }

    @Override
    public void newTask(final String name) {
        this.taskName = name;
        indexPercent = 0;
    }

    @Override
    public void propertyChange(final PropertyChangeEvent event) {
        final String property = event.getProperty();
        if (property != null && property.startsWith(SEARCH_PREFIX)) {
            updateRule();
        }
    }

    @Override
    public void removePanelListener(final ISearchPanelListener listener) {
        listeners.remove(listener);
    }

    @Override
    public void selectAll() {
        updateHistory();
        title.setSelection(new Point(0, title.getText().length()));
    }

    @Override
    public void setEnabled(final boolean enabled) {
        if (isReady()) {
            title.setEnabled(enabled);
            titleEnabled = enabled;
        }
    }

    @Override
    public void setFocus(String text) {
        if (isReady()) {
            if (text == null || text.length() == 0) {
                text = rule.getText();
            }
            if (text != null && text.length() > 0) {
                title.setText(text);
                title.setSelection(new Point(0, text.length()));
                textChanged();
            }
            title.forceFocus();
        }
    }

    @Override
    public void setIndexingState(final int state) {
        indexState = state;

        if (updateInfoThread != null) {
            final UpdateInfoThread thread = updateInfoThread;
            thread.requestStop();
            updateInfoThread = null;
        }
        if (state == INDEXING_STATE_IN_PROGRESS) {
            indexPercent = 0;
            try {
                updateInfoThread = new UpdateInfoThread();
                updateInfoThread.start();
            } catch (final CoreException e) {
                GlancePlugin.log(e.getStatus());
            }
        } else {
            UIUtils.asyncExec(toolBar, new Runnable() {
                @Override
                public void run() {
                    updateInfo(null);
                }
            });
        }
    }

    public void storeSettings() {
        searchSynchronizer.writeConfiguration();
    }

    @Override
    public void updateIndexingPercent(final double percent) {
        indexPercent = percent;
    }

    protected ToolItem createClose(final ToolBar bar) {
        final ToolItem close = new ToolItem(bar, SWT.PUSH);
        final ImageDescriptor image = PlatformUI.getWorkbench().getSharedImages()
                .getImageDescriptor(ISharedImages.IMG_TOOL_DELETE);
        if (image != null) {
            close.setImage(image.createImage());
        }
        close.setToolTipText("Close"); //$NON-NLS-1$
        close.addSelectionListener(new SelectionAdapter() {
            @Override
            public void selected(final SelectionEvent e) {
                closePanel();
            }
        });
        return close;
    }

    protected Composite createContainer(final Composite parent) {
        container = new Composite(parent, SWT.NONE);
        return container;
    }

    protected Label createIcon(final Composite parent) {
        final Label label = new Label(parent, SWT.NONE);
        label.setImage(GlancePlugin.getImage(GlancePlugin.IMG_SEARCH));
        return label;
    }

    protected ToolItem createNextItem(final ToolBar bar) {
        bNext = createTool(bar, "Next", GlancePlugin.IMG_NEXT, new SelectionAdapter() {
            @Override
            public void selected(final SelectionEvent e) {
                findNext();
            }
        });
        return bNext;
    }

    protected ToolItem createPreviousItem(final ToolBar bar) {
        bPrev = createTool(bar, "Previous", GlancePlugin.IMG_PREV, new SelectionAdapter() {
            @Override
            public void selected(final SelectionEvent e) {
                findPrevious();
            }
        });
        return bPrev;
    }

    protected ToolItem createSettingsMenu(final ToolBar bar) {
        final ToolItem settings = new ToolItem(bar, SWT.PUSH);
        settings.setImage(JFaceResources.getImage(PopupDialog.POPUP_IMG_MENU));
        settings.setDisabledImage(JFaceResources.getImage(PopupDialog.POPUP_IMG_MENU_DISABLED));
        settings.setToolTipText("Settings"); //$NON-NLS-1$
        settings.addSelectionListener(new SelectionAdapter() {
            @Override
            public void selected(final SelectionEvent e) {
                showSettings();
            }
        });
        return settings;
    }

    protected Control createText(final Composite parent, final int style) {
        title = new Combo(parent, style | SWT.DROP_DOWN);
        final String text = rule.getText();
        title.setText(text);
        loadHistory();
        if (text != null && text.length() > 0 && result.length == 0) {
            setBackground(false);
        }
        title.addModifyListener(modifyListener);
        title.addListener(SWT.KeyDown, new Listener() {
            @Override
            public void handleEvent(Event event) {
                GlanceEventDispatcher.INSTANCE.dispatchKeyPressed(event);
            }
        });
        title.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        title.setEnabled(titleEnabled);
        return title;
    }

    protected ToolBar createToolBar(final Composite parent) {
        toolBar = new ToolBar(parent, SWT.FLAT);
        GridDataFactory.fillDefaults().align(SWT.END, SWT.CENTER).applyTo(toolBar);
        if (getPreferences().getBoolean(PANEL_DIRECTIONS)) {
            createNextItem(toolBar);
            createPreviousItem(toolBar);
        }
        createIndexing(toolBar);
        createSettingsMenu(toolBar);
        if (getPreferences().getBoolean(PANEL_CLOSE)) {
            createClose(toolBar);
        }
        return toolBar;
    }

    protected void fillMenu(final IMenuManager menu) {
        menu.add(new Separator());
        newAction(menu, SEARCH_CASE_SENSITIVE, LABEL_CASE_SENSITIVE, true);
        final boolean regExp = newAction(menu, SEARCH_REGEXP, LABEL_REGEXP, true).isChecked();
        newAction(menu, SEARCH_CAMEL_CASE, LABEL_CAMEL_CASE, !regExp);
        newAction(menu, SEARCH_WORD_PREFIX, LABEL_WORD_PREFIX, !regExp);
        menu.add(new Separator());
        menu.add(new Action(LABEL_CLEAR_HISTORY) {
            @Override
            public void run() {
                clearHistory();
            }
        });
        //      menu.add(new Separator());
        //      menu.add(new Action("Preferences...") {
        //         @Override
        //         public void run() {
        //            PreferencesUtil.createPreferenceDialogOn(container.getShell(),
        //                  PREFERENCE_PAGE_ID, null, null).open();
        //         }
        //      });
    }

    protected void fireClose() {
        updateHistory();
        saveHistory();
        final Object[] objects = listeners.getListeners();
        for (final Object object : objects) {
            final ISearchPanelListener listener = (ISearchPanelListener) object;
            listener.close();
        }
        getPreferences().removePropertyChangeListener(this);
        if (updateInfoThread != null) {
            updateInfoThread.requestStop();
        }
    }

    protected void fireIndexCanceled() {
        final Object[] objects = listeners.getListeners();
        for (final Object object : objects) {
            final ISearchPanelListener listener = (ISearchPanelListener) object;
            listener.indexCanceled();
        }
    }

    /**
     * @return the preferedWidth
     */
    protected int getPreferedWidth() {
        return preferredWidth;
    }

    /**
     * @return the preferredHeight
     */
    protected int getPreferredHeight() {
        return preferredHeight;
    }

    protected int getTextWidth(final Control control, final int width) {
        final GC gc = new GC(control);
        try {
            gc.setFont(title.getFont());
            return gc.getFontMetrics().getAverageCharWidth() * width;
        } finally {
            gc.dispose();
        }
    }

    protected void setBackground(final boolean found) {
        title.setBackground(found ? GOOD_COLOR : BAD_COLOR);
    }

    protected void showSettings() {
        final MenuManager manager = new MenuManager();
        fillMenu(manager);
        final Menu menu = manager.createContextMenu(getControl());

        final Point location = getControl().getDisplay().getCursorLocation();
        menu.setLocation(location);
        menu.setVisible(true);
    }

    protected void textChanged() {
        final String text = title.getText();
        final boolean empty = text.length() == 0;
        if (empty) {
            textEmpty();
        }
        if (bNext != null && !bNext.isDisposed()) {
            bNext.setEnabled(!empty);
        }
        if (bPrev != null && !bPrev.isDisposed()) {
            bPrev.setEnabled(!empty);
        }
        updateRule();
    }

    protected void textEmpty() {
        setBackground(true);
    }

    protected void updateRule() {
        if (title != null) {
            rule = new SearchRule(title.getText());
            fireRuleChanged(rule);
        }
    }

    protected void updateSelection() {
        fireSelectionChanged();
    }

    private void createIndexing(final ToolBar bar) {
        bIndexing = new ToolItem(bar, SWT.CHECK);
        bIndexing.setDisabledImage(GlancePlugin.getImage(GlancePlugin.IMG_INDEXING_FINISHED));
        bIndexing.addSelectionListener(new SelectionAdapter() {
            @Override
            public void selected(final SelectionEvent e) {
                if (indexState == INDEXING_STATE_INITIAL) {
                    SearchManager.getIntance().index();
                } else if (indexState != INDEXING_STATE_FINISHED) {
                    fireIndexCanceled();
                }
            }
        });
    }

    private ToolItem createTool(final ToolBar bar, final String tip, final String image,
            final SelectionListener listener) {
        final ToolItem item = new ToolItem(bar, SWT.PUSH);
        item.setToolTipText(tip);
        item.setImage(GlancePlugin.getImage(image));
        item.addSelectionListener(listener);
        return item;
    }

    private void fireRuleChanged(final SearchRule rule) {
        historyDirty = true;
        final Object[] objects = listeners.getListeners();
        for (final Object object : objects) {
            final ISearchPanelListener listener = (ISearchPanelListener) object;
            listener.ruleChanged(rule);
        }
    }

    private void fireSelectionChanged() {
        final Object[] objects = listeners.getListeners();
        for (final Object object : objects) {
            final ISearchPanelListener listener = (ISearchPanelListener) object;
            listener.sourceSelectionChanged();
        }
    }

    private String fixItem(final String item) {
        if (item.length() == 0) {
            return null;
        }
        final int index = item.indexOf("\n");
        if (index == 0) {
            return null;
        } else if (index > 0) {
            return item.substring(0, index);
        } else {
            return item;
        }
    }

    private IPreferenceStore getPreferences() {
        return GlancePlugin.getDefault().getPreferenceStore();
    }

    private Color getWaitBGColor() {
        final Display display = PlatformUI.getWorkbench().getDisplay();
        final Color[] color = new Color[1];
        display.syncExec(new Runnable() {
            @Override
            public void run() {
                color[0] = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
            }
        });
        return color[0];
    }

    private void initSize(final Composite composite) {
        final Point size = composite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
        preferredWidth = size.x;
        preferredHeight = size.y;
        preferredWidth -= title.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
        final int widthInChars = getPreferences().getInt(PANEL_TEXT_SIZE);
        preferredWidth += getTextWidth(title, widthInChars) + 15;
    }

    private boolean isReady() {
        return title != null && !title.isDisposed();
    }

    private void loadHistory() {
        findHistory = new ArrayList<String>();
        final String content = getPreferences().getString(HISTORY);
        final String[] items = content.split("\n");
        for (final String item : items) {
            findHistory.add(item);
            title.add(item);
        }
    }

    private CheckAction newAction(final IMenuManager menu, final String name, final String label,
            final boolean enable) {
        return newAction(menu, name, label, enable, null);
    }

    private CheckAction newAction(final IMenuManager menu, final String name, final String label,
            final boolean enable, final String path) {
        final CheckAction action = new CheckAction(name, label, this);
        if (path != null) {
            action.setImageDescriptor(GlancePlugin.getImageDescriptor(path));
        }
        action.setEnabled(enable);
        menu.add(action);
        return action;
    }

    private void saveHistory() {
        final StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < findHistory.size() && i < 8; i++) {
            final String item = findHistory.get(i);
            if (i > 0) {
                buffer.append("\n");
            }
            buffer.append(item);
        }
        getPreferences().putValue(HISTORY, buffer.toString());
    }

    /**
     * Updates history.
     */
    private void updateHistory() {
        if (title != null && !title.isDisposed() && historyDirty) {
            title.removeModifyListener(modifyListener);
            try {
                String findString = title.getText();
                final Point sel = title.getSelection();
                findString = fixItem(findString);
                if (findString != null) {
                    findHistory.remove(findString);
                    findHistory.add(0, findString);
                    title.removeAll();
                    for (final String string : findHistory) {
                        title.add(string);
                    }
                    title.setText(findString);
                    title.setSelection(sel);
                    storeSettings();
                }
            } finally {
                title.addModifyListener(modifyListener);
                historyDirty = false;
            }
        }
    }

    private void updateInfo(final Image image) {
        if (bIndexing == null || bIndexing.isDisposed()) {
            return;
        }

        if (indexState == INDEXING_STATE_DISABLE) {
            bIndexing.setToolTipText("Index component");
            bIndexing.setSelection(false);
            bIndexing.setEnabled(false);
            if (bIndexing.getImage() == null) {
                bIndexing.setImage(GlancePlugin.getImage(GlancePlugin.IMG_START_INDEXING));
            }
        } else if (indexState == INDEXING_STATE_INITIAL) {
            bIndexing.setToolTipText("Index component");
            bIndexing.setSelection(false);
            bIndexing.setImage(GlancePlugin.getImage(GlancePlugin.IMG_START_INDEXING));
            bIndexing.setEnabled(true);
        } else if (indexState == INDEXING_STATE_FINISHED) {
            bIndexing.setToolTipText("Index finished");
            bIndexing.setSelection(false);
            bIndexing.setEnabled(false);
        } else {
            final StringBuffer buffer = new StringBuffer();
            bIndexing.setSelection(true);
            bIndexing.setImage(image);
            if (taskName != null && taskName.length() > 0) {
                buffer.append(taskName);
                buffer.append(": ");
            }
            buffer.append((int) (indexPercent * 100));
            buffer.append("%. Stop indexing.");
            bIndexing.setToolTipText(buffer.toString());
        }
    }
}