org.eclipse.mylyn.internal.sandbox.ui.views.RelatedElementsPopupDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.mylyn.internal.sandbox.ui.views.RelatedElementsPopupDialog.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2009 Tasktop Technologies 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:
 *     Trace Mew - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.sandbox.ui.views;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.PopupDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlExtension;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.context.core.AbstractContextListener;
import org.eclipse.mylyn.context.core.AbstractContextStructureBridge;
import org.eclipse.mylyn.context.core.ContextCore;
import org.eclipse.mylyn.context.core.IInteractionContext;
import org.eclipse.mylyn.context.core.IInteractionElement;
import org.eclipse.mylyn.context.core.IInteractionRelation;
import org.eclipse.mylyn.context.ui.ContextUi;
import org.eclipse.mylyn.internal.context.core.AbstractRelationProvider;
import org.eclipse.mylyn.internal.context.core.ContextCorePlugin;
import org.eclipse.mylyn.internal.context.ui.ContextUiPlugin;
import org.eclipse.mylyn.internal.context.ui.DoiOrderSorter;
import org.eclipse.mylyn.internal.context.ui.views.QuickOutlinePatternAndInterestFilter;
import org.eclipse.mylyn.internal.sandbox.ui.DelegatingContextLabelProvider;
import org.eclipse.mylyn.internal.sandbox.ui.SandboxUiImages;
import org.eclipse.mylyn.internal.sandbox.ui.SandboxUiPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.misc.StringMatcher;

/**
 * Derived from {@link QuickOutlinePopupDialog}
 * 
 * @author Tracy Mew
 */
public class RelatedElementsPopupDialog extends PopupDialog implements IInformationControl,
        IInformationControlExtension, IInformationControlExtension2, DisposeListener {

    public static final String ID = "org.eclipse.mylyn.context.ui.navigator.context.related";

    private TreeViewer viewer;

    private Text fFilterText;

    private StringMatcher fStringMatcher;

    private QuickOutlinePatternAndInterestFilter namePatternFilter;

    private final DelegatingContextLabelProvider labelProvider = new DelegatingContextLabelProvider();

    private final DegreeZeroAction zero = new DegreeZeroAction();

    private final DegreeOneAction one = new DegreeOneAction();

    private final DegreeTwoAction two = new DegreeTwoAction();

    private final DegreeThreeAction three = new DegreeThreeAction();

    private final DegreeFourAction four = new DegreeFourAction();

    private final DegreeFiveAction five = new DegreeFiveAction();

    private int degree = 2;

    public RelatedElementsPopupDialog(Shell parent, int shellStyle) {
        super(parent, shellStyle, true, true, true, true, true, null, "Context Search");
        ContextCore.getContextManager().addListener(REFRESH_UPDATE_LISTENER);
        for (AbstractRelationProvider provider : ContextCorePlugin.getDefault().getRelationProviders()) {
            provider.setEnabled(true);
        }
        create();
    }

    /**
     * For testing.
     */
    private boolean syncExecForTesting = true;

    private final AbstractContextListener REFRESH_UPDATE_LISTENER = new AbstractContextListener() {

        @Override
        public void interestChanged(List<IInteractionElement> nodes) {
            refresh(nodes.get(nodes.size() - 1), false);
        }

        @Override
        public void contextActivated(IInteractionContext taskscape) {
            refreshRelatedElements();
            refresh(null, true);
        }

        @Override
        public void contextDeactivated(IInteractionContext taskscape) {
            refresh(null, true);
        }

        @Override
        public void contextCleared(IInteractionContext context) {
            refresh(null, true);
        }

        @Override
        public void landmarkAdded(IInteractionElement node) {
            refresh(null, true);
        }

        @Override
        public void landmarkRemoved(IInteractionElement node) {
            refresh(null, true);
        }

        // TODO move this somewhere?
        //      public void relationsChanged(IInteractionElement node) {
        //         refresh(node, true);
        //      }

        @Override
        public void elementsDeleted(List<IInteractionElement> elements) {
            refresh(null, true);
        }
    };

    @Override
    protected Control createDialogArea(Composite parent) {
        createViewer(parent);
        createUIListenersTreeViewer();
        addDisposeListener(this);

        return viewer.getControl();
    }

    private void createViewer(Composite parent) {
        viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);

        viewer.setUseHashlookup(true);

        viewer.setContentProvider(new ContextContentProvider(viewer.getTree(), parent.getShell(), true));

        viewer.setLabelProvider(new DecoratingLabelProvider(labelProvider,
                PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator()));

        viewer.setSorter(new DoiOrderSorter());

        try {
            viewer.getControl().setRedraw(false);
            viewer.setInput(getShell());
        } finally {
            refreshRelatedElements();
            viewer.getControl().setRedraw(true);
        }
    }

    private void createUIListenersTreeViewer() {
        final Tree tree = viewer.getTree();
        tree.addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                if (e.character == 0x1B) {
                    // Dispose on ESC key press
                    dispose();
                }
            }

            public void keyReleased(KeyEvent e) {
                // ignore
            }
        });

        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseDoubleClick(MouseEvent e) {
                handleTreeViewerMouseUp(tree, e);
            }
        });

        tree.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ignore
            }

            public void widgetDefaultSelected(SelectionEvent e) {
                gotoSelectedElement();
            }
        });
    }

    private void handleTreeViewerMouseUp(final Tree tree, MouseEvent e) {
        if ((tree.getSelectionCount() < 1) || (e.button != 1) || (tree.equals(e.getSource()) == false)) {
            return;
        }
        // Selection is made in the selection changed listener
        Object object = tree.getItem(new Point(e.x, e.y));
        TreeItem selection = tree.getSelection()[0];
        if (selection.equals(object)) {
            gotoSelectedElement();
        }
    }

    private void gotoSelectedElement() {
        Object selectedElement = getSelectedElement();
        if (selectedElement == null) {
            return;
        }
        IInteractionElement node = null;
        if (selectedElement instanceof IInteractionElement) {
            node = (IInteractionElement) selectedElement;
        } else if (!(selectedElement instanceof IInteractionRelation)) {
            AbstractContextStructureBridge bridge = ContextCore.getStructureBridge(selectedElement);
            String handle = bridge.getHandleIdentifier(selectedElement);
            node = ContextCore.getContextManager().getElement(handle);
        }
        if (node != null) {
            ContextUi.getUiBridge(node.getContentType()).open(node);
        }
        dispose();
    }

    private Object getSelectedElement() {
        if (viewer == null) {
            return null;
        }
        return ((IStructuredSelection) viewer.getSelection()).getFirstElement();
    }

    public void addDisposeListener(DisposeListener listener) {
        getShell().addDisposeListener(listener);
    }

    public void addFocusListener(FocusListener listener) {
        getShell().addFocusListener(listener);
    }

    public Point computeSizeHint() {
        // Note that it already has the persisted size if persisting is enabled.
        return getShell().getSize();
    }

    public boolean isFocusControl() {
        if (viewer.getControl().isFocusControl() || fFilterText.isFocusControl()) {
            return true;
        }
        return false;
    }

    public void removeDisposeListener(DisposeListener listener) {
        getShell().removeDisposeListener(listener);
    }

    public void removeFocusListener(FocusListener listener) {
        getShell().removeFocusListener(listener);
    }

    public void setBackgroundColor(Color background) {
        applyBackgroundColor(background, getContents());
    }

    public void setFocus() {
        viewer.refresh();
        viewer.getControl().setFocus();
        fFilterText.setFocus();
        getShell().forceFocus();
    }

    public void setForegroundColor(Color foreground) {
        applyForegroundColor(foreground, getContents());
    }

    public void setInformation(String information) {
        // See IInformationControlExtension2
    }

    public void setLocation(Point location) {
        /*
         * If the location is persisted, it gets managed by PopupDialog - fine. Otherwise, the location is
         * computed in Window#getInitialLocation, which will center it in the parent shell / main
         * monitor, which is wrong for two reasons:
         * - we want to center over the editor / subject control, not the parent shell
         * - the center is computed via the initalSize, which may be also wrong since the size may 
         *   have been updated since via min/max sizing of AbstractInformationControlManager.
         * In that case, override the location with the one computed by the manager. Note that
         * the call to constrainShellSize in PopupDialog.open will still ensure that the shell is
         * entirely visible.
         */
        if (getPersistLocation() == false || getDialogSettings() == null) {
            getShell().setLocation(location);
        }
    }

    public void setSize(int width, int height) {
        getShell().setSize(width, height);
    }

    public void setSizeConstraints(int maxWidth, int maxHeight) {
        // Ignore
    }

    public void setVisible(boolean visible) {
        if (visible) {
            open();
        } else {
            saveDialogBounds(getShell());
            getShell().setVisible(false);
        }
    }

    public boolean hasContents() {
        if ((viewer == null) || (viewer.getInput() == null)) {
            return false;
        }
        return true;
    }

    public void setInput(Object input) {
        // Input comes from PDESourceInfoProvider.getInformation2()
        // The input should be a model object of some sort
        // Turn it into a structured selection and set the selection in the tree
        if (input != null) {
            viewer.setSelection(new StructuredSelection(input));
        }
    }

    public void widgetDisposed(DisposeEvent e) {
        // Note: We do not reuse the dialog
        viewer = null;
        fFilterText = null;
    }

    @Override
    protected Control createTitleControl(Composite parent) {
        // Applies only to dialog title - not body.  See createDialogArea
        // Create the text widget
        createUIWidgetFilterText(parent);
        // Add listeners to the text widget
        createUIListenersFilterText();
        // Return the text widget
        return fFilterText;
    }

    private void createUIWidgetFilterText(Composite parent) {
        // Create the widget
        fFilterText = new Text(parent, SWT.NONE);
        // Set the font 
        GC gc = new GC(parent);
        gc.setFont(parent.getFont());
        FontMetrics fontMetrics = gc.getFontMetrics();
        gc.dispose();
        // Create the layout
        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        data.heightHint = Dialog.convertHeightInCharsToPixels(fontMetrics, 1);
        data.horizontalAlignment = GridData.FILL;
        data.verticalAlignment = GridData.CENTER;
        fFilterText.setLayoutData(data);
    }

    private void createUIListenersFilterText() {
        fFilterText.addKeyListener(new KeyListener() {
            public void keyPressed(KeyEvent e) {
                if (e.keyCode == 0x0D) {
                    // Return key was pressed
                    gotoSelectedElement();
                } else if (e.keyCode == SWT.ARROW_DOWN) {
                    // Down key was pressed
                    viewer.getTree().setFocus();
                } else if (e.keyCode == SWT.ARROW_UP) {
                    // Up key was pressed
                    viewer.getTree().setFocus();
                } else if (e.character == 0x1B) {
                    // Escape key was pressed
                    dispose();
                }
            }

            public void keyReleased(KeyEvent e) {
                // NO-OP
            }
        });
        // Handle text modify events
        fFilterText.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                String text = ((Text) e.widget).getText();
                int length = text.length();
                if (length > 0) {
                    // Append a '*' pattern to the end of the text value if it
                    // does not have one already
                    if (text.charAt(length - 1) != '*') {
                        text = text + '*';
                    }
                    // Prepend a '*' pattern to the beginning of the text value
                    // if it does not have one already
                    if (text.charAt(0) != '*') {
                        text = '*' + text;
                    }
                }
                // Set and update the pattern
                setMatcherString(text, true);
            }
        });
    }

    /**
     * Sets the patterns to filter out for the receiver.
     * <p>
     * The following characters have special meaning: ? => any character * => any string
     * </p>
     * 
     * @param pattern
     *            the pattern
     * @param update
     *            <code>true</code> if the viewer should be updated
     */
    private void setMatcherString(String pattern, boolean update) {
        if (pattern.length() == 0) {
            fStringMatcher = null;
        } else {
            fStringMatcher = new StringMatcher(pattern, true, false);
        }
        // Update the name pattern filter on the tree viewer
        namePatternFilter.setStringMatcher(fStringMatcher);
        // Update the tree viewer according to the pattern
        if (update) {
            stringMatcherUpdated();
        }
    }

    /**
     * The string matcher has been modified. The default implementation refreshes the view and selects the first matched
     * element
     */
    private void stringMatcherUpdated() {
        // Refresh the tree viewer to re-filter
        viewer.getControl().setRedraw(false);
        viewer.refresh();
        viewer.expandAll();
        selectFirstMatch();
        viewer.getControl().setRedraw(true);
    }

    /**
     * Selects the first element in the tree which matches the current filter pattern.
     */
    private void selectFirstMatch() {
        Tree tree = viewer.getTree();
        Object element = findFirstMatchToPattern(tree.getItems());
        if (element != null) {
            viewer.setSelection(new StructuredSelection(element), true);
        } else {
            viewer.setSelection(StructuredSelection.EMPTY);
        }
    }

    /**
     * @param items
     * @return
     */
    private Object findFirstMatchToPattern(TreeItem[] items) {
        // Match the string pattern against labels
        ILabelProvider labelProvider = (ILabelProvider) viewer.getLabelProvider();
        // Process each item in the tree
        for (TreeItem item : items) {
            Object element = item.getData();
            // Return the first element if no pattern is set
            if (fStringMatcher == null) {
                return element;
            }
            // Return the element if it matches the pattern
            if (element != null) {
                String label = labelProvider.getText(element);
                if (fStringMatcher.match(label)) {
                    return element;
                }
            }
            // Recursively check the elements children for a match
            element = findFirstMatchToPattern(item.getItems());
            // Return the child element match if found
            if (element != null) {
                return element;
            }
        }
        // No match found
        return null;
    }

    /**
     * fix for bug 109235
     * 
     * @param node
     * @param updateLabels
     */
    void refresh(final IInteractionElement node, final boolean updateLabels) {
        if (!syncExecForTesting) { // for testing
            // if (viewer != null && !viewer.getTree().isDisposed()) {
            // internalRefresh(node, updateLabels);
            // }
            PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {
                public void run() {
                    try {
                        internalRefresh(node, updateLabels);
                    } catch (Throwable t) {
                        StatusHandler.log(new Status(IStatus.WARNING, SandboxUiPlugin.ID_PLUGIN,
                                "Context search refresh failed", t));
                    }
                }
            });
        } else {
            PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
                public void run() {
                    try {
                        internalRefresh(node, updateLabels);
                    } catch (Throwable t) {
                        StatusHandler.log(new Status(IStatus.WARNING, SandboxUiPlugin.ID_PLUGIN,
                                "Context search refresh failed", t));
                    }
                }
            });
        }

    }

    private void internalRefresh(final IInteractionElement node, boolean updateLabels) {
        Object toRefresh = null;
        if (node != null) {
            AbstractContextStructureBridge bridge = ContextCore.getStructureBridge(node.getContentType());
            toRefresh = bridge.getObjectForHandle(node.getHandleIdentifier());
        }
        if (viewer != null && !viewer.getTree().isDisposed()) {
            viewer.getControl().setRedraw(false);
            if (toRefresh != null && containsNode(viewer.getTree(), toRefresh)) {
                viewer.refresh(toRefresh, updateLabels);
            } else if (node == null) {
                viewer.refresh();
            }
            viewer.expandAll();
            viewer.getControl().setRedraw(true);
        }
    }

    private boolean containsNode(Tree tree, Object object) {
        boolean contains = false;
        for (int i = 0; i < tree.getItems().length; i++) {
            TreeItem item = tree.getItems()[i];
            if (object.equals(item.getData())) {
                contains = true;
            }
        }
        return contains;
    }

    public void refreshRelatedElements() {
        try {
            for (AbstractRelationProvider provider : ContextCorePlugin.getDefault().getRelationProviders()) {
                List<AbstractRelationProvider> providerList = new ArrayList<AbstractRelationProvider>();
                providerList.add(provider);
                updateDegreesOfSeparation(providerList, provider.getCurrentDegreeOfSeparation());
            }
        } catch (Throwable t) {
            StatusHandler.log(new Status(IStatus.WARNING, SandboxUiPlugin.ID_PLUGIN,
                    "Could not refresh related elements", t));
        }
    }

    public void updateDegreesOfSeparation(Collection<AbstractRelationProvider> providers, int degreeOfSeparation) {
        for (AbstractRelationProvider provider : providers) {
            updateDegreeOfSeparation(provider, degreeOfSeparation);
        }
    }

    public void updateDegreeOfSeparation(AbstractRelationProvider provider, int degreeOfSeparation) {
        ContextCorePlugin.getContextManager().resetLandmarkRelationshipsOfKind(provider.getId());
        ContextUiPlugin.getDefault().getPreferenceStore().setValue(provider.getGenericId(), degreeOfSeparation);
        provider.setDegreeOfSeparation(degreeOfSeparation);
        for (IInteractionElement element : ContextCore.getContextManager().getActiveContext().getInteresting()) {
            if (element.getInterest().isLandmark()) {
                provider.landmarkAdded(element);
            }
        }
    }

    @Override
    protected void fillDialogMenu(IMenuManager dialogMenu) {
        MenuManager degMenu = new MenuManager("Degree of Separation");
        degMenu.add(zero);
        degMenu.add(one);
        degMenu.add(two);
        degMenu.add(three);
        degMenu.add(four);
        degMenu.add(five);
        check(getDegree());
        dialogMenu.add(degMenu);
        dialogMenu.add(new Separator());

        IAction qualifyElements = new ShowQualifiedNamesAction(this);
        dialogMenu.add(qualifyElements);
        dialogMenu.add(new Separator());

        super.fillDialogMenu(dialogMenu);
    }

    public void setQualifiedNameMode(boolean qualifiedNameMode) {
        DelegatingContextLabelProvider.setQualifyNamesMode(qualifiedNameMode);
        refresh(null, true);
    }

    private class DegreeZeroAction extends Action {
        DegreeZeroAction() {
            super(JFaceResources.getString("0: Disabled"), //$NON-NLS-1$
                    IAction.AS_CHECK_BOX);
        }

        @Override
        public void run() {
            check(0);
            refreshAction(0);

        }
    }

    private class DegreeOneAction extends Action {
        DegreeOneAction() {
            super(JFaceResources.getString("1: Landmark Resources"), //$NON-NLS-1$
                    IAction.AS_CHECK_BOX);
        }

        @Override
        public void run() {
            check(1);
            refreshAction(1);
        }
    }

    private class DegreeTwoAction extends Action {
        DegreeTwoAction() {
            super(JFaceResources.getString("2: Interesting Resources"), //$NON-NLS-1$
                    IAction.AS_CHECK_BOX);
        }

        @Override
        public void run() {
            check(2);
            refreshAction(2);
        }
    }

    private class DegreeThreeAction extends Action {
        DegreeThreeAction() {
            super(JFaceResources.getString("3: Interesting Projects"), //$NON-NLS-1$
                    IAction.AS_CHECK_BOX);
        }

        @Override
        public void run() {
            check(3);
            refreshAction(3);
        }
    }

    private class DegreeFourAction extends Action {
        DegreeFourAction() {
            super(JFaceResources.getString("4: Project Dependencies"), //$NON-NLS-1$
                    IAction.AS_CHECK_BOX);
        }

        @Override
        public void run() {
            check(4);
            refreshAction(4);
        }
    }

    private class DegreeFiveAction extends Action {
        DegreeFiveAction() {
            super(JFaceResources.getString("5: Entire Workspace (slow)"), //$NON-NLS-1$
                    IAction.AS_CHECK_BOX);
        }

        @Override
        public void run() {
            check(5);
            refreshAction(5);
        }
    }

    private void refreshAction(int degOfSep) {
        try {
            for (AbstractRelationProvider provider : ContextCorePlugin.getDefault().getRelationProviders()) {
                List<AbstractRelationProvider> providerList = new ArrayList<AbstractRelationProvider>();
                providerList.add(provider);

                if (provider.getCurrentDegreeOfSeparation() != degOfSep) {
                    updateDegreesOfSeparation(providerList, degOfSep);
                    degree = provider.getCurrentDegreeOfSeparation();
                }
            }

        } catch (Throwable t) {
            StatusHandler.log(new Status(IStatus.WARNING, SandboxUiPlugin.ID_PLUGIN,
                    "Could not refresh related elements", t));
        }
    }

    private int getDegree() {
        for (AbstractRelationProvider provider : ContextCorePlugin.getDefault().getRelationProviders()) {
            degree = provider.getCurrentDegreeOfSeparation();
            break;
        }
        return degree;
    }

    private void check(int degree) {
        zero.setChecked(false);
        one.setChecked(false);
        two.setChecked(false);
        three.setChecked(false);
        four.setChecked(false);
        five.setChecked(false);
        switch (degree) {
        case 0:
            zero.setChecked(true);
            break;
        case 1:
            one.setChecked(true);
            break;
        case 2:
            two.setChecked(true);
            break;
        case 3:
            three.setChecked(true);
            break;
        case 4:
            four.setChecked(true);
            break;
        default:
            five.setChecked(true);
        }
    }

    private class ShowQualifiedNamesAction extends Action {

        public static final String LABEL = "Qualify Member Names";

        public static final String ID = "org.eclipse.mylyn.ui.views.elements.qualify";

        private final RelatedElementsPopupDialog dialog;

        public ShowQualifiedNamesAction(RelatedElementsPopupDialog dialog) {
            super(LABEL, IAction.AS_CHECK_BOX);
            this.dialog = dialog;
            setId(ID);
            setText(LABEL);
            setToolTipText(LABEL);
            setImageDescriptor(SandboxUiImages.QUALIFY_NAMES);
            update(ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(ID));
        }

        public void update(boolean on) {
            dialog.setQualifiedNameMode(on);
            setChecked(on);
            ContextUiPlugin.getDefault().getPreferenceStore().setValue(ID, on);
        }

        @Override
        public void run() {
            update(!ContextUiPlugin.getDefault().getPreferenceStore().getBoolean(ID));
        }
    }

    /**
     * Set to false for testing
     */
    public void setSyncExecForTesting(boolean asyncRefreshMode) {
        this.syncExecForTesting = asyncRefreshMode;
    }

    public void dispose() {
        ContextCore.getContextManager().removeListener(REFRESH_UPDATE_LISTENER);
        super.close();
    }

    @Override
    protected Point getInitialSize() {
        return new Point(400, 500);
    }

}