com.mentor.nucleus.bp.core.util.UIUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.mentor.nucleus.bp.core.util.UIUtil.java

Source

//=====================================================================
//
//File:      $RCSfile: UIUtil.java,v $
//Version:   $Revision: 1.29 $
//Modified:  $Date: 2013/06/12 13:08:18 $
//
//(c) Copyright 2004-2014 by Mentor Graphics Corp. All rights reserved.
//
//=====================================================================
// Licensed under the Apache License, Version 2.0 (the "License"); you may not 
// use this file except in compliance with the License.  You may obtain a copy 
// of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   See the 
// License for the specific language governing permissions and limitations under
// the License.
//=====================================================================

package com.mentor.nucleus.bp.core.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.properties.PropertySheet;
import org.osgi.framework.Bundle;

import com.mentor.nucleus.bp.core.CorePlugin;
import com.mentor.nucleus.bp.core.Ooaofooa;
import com.mentor.nucleus.bp.core.SystemModel_c;
import com.mentor.nucleus.bp.core.common.ClassQueryInterface_c;
import com.mentor.nucleus.bp.core.common.ModelElement;
import com.mentor.nucleus.bp.core.common.NonRootModelElement;
import com.mentor.nucleus.bp.core.common.PersistenceManager;
import com.mentor.nucleus.bp.core.ui.RenameAction;
import com.mentor.nucleus.bp.core.ui.dialogs.ScrolledTextDialog;

/**
 * Utility methods related to this product's UI.
 */
public class UIUtil {
    private static boolean displayYesNoQuestion_isYes = true;
    private static volatile boolean booleanDialogResult = false;

    /**
     * 
     * @param element null to refresh whole tree
     */
    public static void refresh(final Object element) {
        PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {

            @Override
            public void run() {
                StructuredViewer viewer = null;
                Class<?> explorerViewClass = null;
                Object elementToRefresh = element;

                try {
                    Bundle ui_explorer = Platform.getBundle("com.mentor.nucleus.bp.ui.explorer");//$NON-NLS-1$
                    explorerViewClass = ui_explorer.loadClass("com.mentor.nucleus.bp.ui.explorer.ExplorerView"); //$NON-NLS-1$
                } catch (Exception cnf) {
                    CorePlugin.logError("Problem accessing GraphicsUtil class ", cnf); //$NON-NLS-1$
                    return;
                }

                Class<?>[] type;
                try {
                    type = new Class<?>[] {};

                    Method getExplorerTreeViewer = explorerViewClass.getMethod("getExplorerTreeViewer", type); //$NON-NLS-1$
                    Object[] args = new Object[] {};
                    viewer = (StructuredViewer) getExplorerTreeViewer.invoke(explorerViewClass, args);
                } catch (Exception e) {
                    CorePlugin.logError("Error invoking getCanvasEditorTitle(NRME) in GraphicsUtil  ", e); //$NON-NLS-1$
                }
                if (element instanceof IProject) {
                    elementToRefresh = SystemModel_c.SystemModelInstance(Ooaofooa.getDefaultInstance(),
                            new ClassQueryInterface_c() {
                                public boolean evaluate(Object c) {
                                    return ((SystemModel_c) c).getName().equals(((IProject) element).getName());
                                }

                            }, false);
                }
                refreshViewer(viewer, elementToRefresh);
                IEditorReference[] editorReferences = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
                        .getActivePage().getEditorReferences();
                for (IEditorReference reference : editorReferences) {
                    IEditorPart editor = reference.getEditor(false);
                    if (editor != null) {
                        Method method = null;
                        try {
                            method = editor.getClass().getMethod("refresh", new Class[0]); //$NON-NLS-1$
                        } catch (SecurityException e) {
                            CorePlugin.logError("Unable to locate method for refreshing graphical editors.", e);
                        } catch (NoSuchMethodException e) {
                            // most editors will not have this method, for those we do not
                            // want to refresh anyway
                        }
                        if (method != null) {
                            try {
                                method.invoke(editor, new Object[0]);
                            } catch (IllegalArgumentException e) {
                                CorePlugin.logError("Unable to invoke refresh method for graphical editor.", e);
                            } catch (IllegalAccessException e) {
                                CorePlugin.logError("Unable to invoke refresh method for graphical editor.", e);
                            } catch (InvocationTargetException e) {
                                CorePlugin.logError("Unable to invoke refresh method for graphical editor.", e);
                            }
                        }
                    }
                }
            }
        });
    }

    public static void refreshViewer(final StructuredViewer viewer) {
        refreshViewer(viewer, null);
    }

    /**
     * Performs a refresh of the given viewer, on the UI thread,
     * starting with the given element.  If no element is given,
     * the refresh starts with the viewer's root element.
     */
    private static HashMap<StructuredViewer, ArrayList<Object>> updateList = new HashMap<StructuredViewer, ArrayList<Object>>();

    public static void refreshViewer(final StructuredViewer viewer, final Object element) {
        Object target = element;
        if (viewer == null)
            return;
        // if the given viewer hasn't been disposed
        Control control = viewer.getControl();
        if (!control.isDisposed()) {
            if (target instanceof NonRootModelElement) {
                IFile f = ((NonRootModelElement) target).getFile();
                if (f == null || !f.getProject().isOpen()) {
                    target = null;
                }
            } else if (target instanceof Ooaofooa) {
                IFile f = ((Ooaofooa) target).getFile();
                if (f == null || !f.getProject().isOpen()) {
                    refresh(viewer, null);
                }
            }
            boolean queueRefresh = true;
            if (updateList.containsKey(viewer)) {
                // if the element is already scheduled for a refresh or if the whole
                // tree is going to be refreshed, don't repeat the refresh
                if (updateList.get(viewer).contains(target) || updateList.get(viewer).contains(null)) {
                    queueRefresh = false;
                }
            }
            if (queueRefresh) {
                synchronized (updateList) {
                    Display display = control.getDisplay();
                    // ask the viewer's UI thread to perform the refresh
                    final Object f_target = target;
                    display.asyncExec(new Runnable() {
                        public void run() {
                            updateList.get(viewer).remove(f_target);
                            refresh(viewer, f_target);
                        }
                    });
                    if (!updateList.containsKey(viewer)) {
                        updateList.put(viewer, new ArrayList<Object>());
                    }
                    updateList.get(viewer).add(f_target);
                }
            }

        }
    }

    /**
     * Makes the appropriate call to refresh() on the given viewer, depending on
     * whether the given element is non-null.
     */
    private static void refresh(final StructuredViewer viewer, final Object element) {
        WorkspaceJob job = new WorkspaceJob("Refreshing views") {

            @Override
            public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
                PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {

                    @Override
                    public void run() {
                        if (!viewer.getControl().isDisposed()) {
                            if (element != null)
                                viewer.refresh(element);
                            else
                                viewer.refresh();
                        }
                    }
                });
                return Status.OK_STATUS;
            }
        };
        job.setRule(ResourcesPlugin.getWorkspace().getRoot());
        job.schedule();
    }

    /**
     * Makes a call to the given control's redraw() method, ensuring
     * that the call occurs on the UI thread.  If the calling thread
     * is not the UI thread, the UI thread is asked to make the call. 
     */
    public static void redrawControl(final Control control) {
        // if the given control has been disposed, there is nothing to do
        if (control.isDisposed())
            return;

        // if we're running on the UI thread
        Display display = control.getDisplay();
        if (Display.getCurrent() == display) {
            // make the redraw call directly
            control.redraw();
        }

        // otherwise
        else {
            // ask the UI thread to make the redraw call
            display.asyncExec(new Runnable() {
                public void run() {
                    control.redraw();
                }
            });
        }
    }

    public static Menu getMenuForTreeItem(TreeViewer viewer, TreeItem item) {
        Tree sevTree = viewer.getTree();
        viewer.setSelection(new StructuredSelection(item.getData()));
        sevTree.setSelection(item);
        UIUtil.dispatchAll();

        Menu menu = viewer.getTree().getMenu();
        return menu;
    }

    /**
     * Causes the context menu for the given control to be populated,
     * by temporarily having it displayed.
     */
    public static void getContextMenuPopulated(Control control) {
        // have the menu closed a short while after it's displayed, below,
        // once it's very likely to have been fully populated
        final Menu menu = control.getMenu();
        Display display = control.getDisplay();
        display.timerExec(10, new Runnable() {
            public void run() {
                menu.setVisible(false);
            }
        });

        // display the context menu to get it populated 
        menu.setVisible(true);
        while (display.readAndDispatch())
            ;
    }

    /**
     * Is a shorthand method for the enclosed code.
     */
    public static void dispatchAll() {
        if (PlatformUI.isWorkbenchRunning()) { // If we are running in "truly headless" more there is no workbench 
            if (Display.getCurrent() != null) {
                while (Display.getCurrent().readAndDispatch())
                    ;
            }
        }
    }

    /**
     * Returns the tree control displayed for the currently active properties
     * sheet page.  This method requires that the properties view is currently 
     * visible within the workbench. 
     */
    public static Tree getPropertyTree() {
        PropertySheet sheet = (PropertySheet) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                .findView(IPageLayout.ID_PROP_SHEET);
        return (Tree) sheet.getCurrentPage().getControl();
    }

    private static void outputTextForheadlessRun(BPMessageTypes type, String title, String text, String value) {
        String outputString = type.getText() + ": " + title + ". " + text;
        if (!value.isEmpty()) {
            outputString += ".  Value:  " + value;
        }
        CorePlugin.out.println(outputString);
    }

    /**
     * Opens a scrollable dialog with the given data
     */
    public static boolean openScrollableTextDialog(Shell parentShell, boolean allowCancel, String title,
            String textContents, String message, String optionalText, String preferenceKey, boolean defaultReturn) {
        if (CoreUtil.IsRunningHeadless) {
            outputTextForheadlessRun(BPMessageTypes.QUESTION, title, message, String.valueOf(defaultReturn));
        } else {
            ScrolledTextDialog dialog = new ScrolledTextDialog(parentShell, allowCancel, title, textContents,
                    message, optionalText, preferenceKey);
            int result = dialog.open();
            if (result == Window.OK) {
                return true;
            } else {
                return false;
            }
        }
        return defaultReturn;
    }

    /**
     * Shows an error dialog with the given title and message.
     */
    public static void showErrorDialog(String title, String message) {
        IWorkbenchWindow activeWindow = null;
        Shell parentShell = null;
        if (!CoreUtil.IsRunningHeadless) {
            activeWindow = CorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
        }
        if (activeWindow != null) {
            parentShell = activeWindow.getShell();
        }
        openError(parentShell, title, message);
    }

    public enum BPMessageTypes {
        INFORMATION("Information"), WARNING("Warning"), ERROR("Error"), CONFIRM("Confirm"), QUESTION(
                "Question"), INPUT("Input");

        private String description;

        BPMessageTypes(String p_description) {
            description = p_description;
        }

        public String getText() {
            return description;
        }
    };

    public static void openError(Shell parent, String title, final String message) {
        openError(parent, title, message, false);
    }

    public static void openError(Shell parent, String title, final String message,
            boolean showTechSupportContactInfo) {
        internalDialogHandler(parent, title, message, BPMessageTypes.ERROR, showTechSupportContactInfo);
    }

    public static void openErrorWithContactInfo(final String message) {
        openError(null, null, message, true);
    }

    public static void openError(final String message) {
        openError(null, null, message, false);
    }

    public static void displayError(final String message) {
        openError(message);
    }

    public static void openWarning(Shell parent, String title, final String message) {
        internalDialogHandler(parent, title, message, BPMessageTypes.WARNING, false);
    }

    public static void openWarning(final String message) {
        openWarning(null, null, message);
    }

    public static void displayWarning(final String message) {
        openWarning(message);
    }

    public static void openInformation(Shell parent, String title, final String message) {
        internalDialogHandler(parent, title, message, BPMessageTypes.INFORMATION, false);
    }

    public static void openInformation(final String message) {
        openInformation(null, null, message);
    }

    public static boolean openConfirm(Shell parent, String title, final String message, boolean defaultValue) {
        booleanDialogResult = defaultValue;
        return internalDialogHandler(parent, title, message, BPMessageTypes.CONFIRM, false);
    }

    public static boolean openConfirm(final String message, boolean defaultValue) {
        return openConfirm(null, null, message, defaultValue);
    }

    public static boolean openQuestion(Shell parent, String title, final String message, boolean defaultValue) {
        booleanDialogResult = defaultValue;
        return internalDialogHandler(parent, title, message, BPMessageTypes.QUESTION, false);
    }

    public static boolean openQuestion(final String message, boolean defaultValue) {
        return openQuestion(null, null, message, defaultValue);
    }

    public static void showMessageDialoginLaunch(Shell p_parent, String p_title, String p_msg,
            BPMessageTypes p_type) {
        internalDialogHandler(p_parent, p_title, p_msg, p_type, false);
    }

    /**
     * Note this "MessageDialog" currently only supports an array of 2 dialog button
     * labels.   This is why the result is a boolean.  It simply behaves in
     * a similar manner as if a yes/no question had been asked (offset 0 is
     * yes and offset 1 is no).   If additional buttons are ever needed this
     * will need to be modified to handle it.
     */
    public static boolean openMessageDialog(Shell parentShell, String dialogTitle, Image dialogTitleImage,
            String dialogMessage, BPMessageTypes dialogType, String[] dialogButtonLabels, int defaultIndex) {
        int standardDialogType = MessageDialog.WARNING;
        if (dialogType == BPMessageTypes.ERROR) {
            standardDialogType = MessageDialog.ERROR;
        } else if ((dialogType == BPMessageTypes.INFORMATION)) {
            standardDialogType = MessageDialog.INFORMATION;
        }
        boolean result = (defaultIndex == MessageDialog.OK);
        if (CoreUtil.IsRunningHeadless) {
            outputTextForheadlessRun(dialogType, dialogTitle, dialogMessage, "");
        } else {
            MessageDialog dialog = new MessageDialog(parentShell, dialogTitle, dialogTitleImage, dialogMessage,
                    standardDialogType, dialogButtonLabels, defaultIndex);
            dialog.setBlockOnOpen(true);
            int actualResult = dialog.open();
            result = MessageDialog.OK == actualResult;
        }
        return result;
    }

    private static class BPMessageDialog implements Runnable {
        Shell m_parent;
        final String m_title;
        final String m_msg;
        final BPMessageTypes m_type;

        BPMessageDialog(Shell p_parent, final String p_title, final String p_msg, final BPMessageTypes p_type) {
            m_parent = p_parent;
            m_title = p_title;
            m_msg = p_msg;
            m_type = p_type;
        }

        public void run() {
            boolean logTheMessage = false;
            if (m_type == BPMessageTypes.ERROR) {
                logTheMessage = true;
            }

            if (m_parent == null && !CoreUtil.IsRunningHeadless) {
                IWorkbenchWindow activeWBWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                Shell parentShell = null;
                if (activeWBWindow != null) {
                    m_parent = activeWBWindow.getShell();
                }
            }

            if (CoreUtil.IsRunningHeadless) {
                // if headless there shouldn't be a parent shell, but this is just to be sure
                m_parent = null;
            }

            if (m_parent != null && !CoreUtil.IsRunningHeadless) {
                if (m_type == BPMessageTypes.INFORMATION) {
                    org.eclipse.jface.dialogs.MessageDialog.openInformation(m_parent, m_title, m_msg);
                } else if (m_type == BPMessageTypes.WARNING) {
                    org.eclipse.jface.dialogs.MessageDialog.openWarning(m_parent, m_title, m_msg);
                } else if (m_type == BPMessageTypes.ERROR) {
                    org.eclipse.jface.dialogs.MessageDialog.openError(m_parent, m_title, m_msg);
                } else if (m_type == BPMessageTypes.CONFIRM) {
                    booleanDialogResult = org.eclipse.jface.dialogs.MessageDialog.openConfirm(m_parent, m_title,
                            m_msg);
                } else if (m_type == BPMessageTypes.QUESTION) {
                    booleanDialogResult = org.eclipse.jface.dialogs.MessageDialog.openQuestion(m_parent, m_title,
                            m_msg);
                }
            } else if (CoreUtil.IsRunningHeadless) {
                outputTextForheadlessRun(m_type, m_title, m_msg, "");
            } else {
                // No Active shell is available for a UI dialog.
                logTheMessage = true;
            }
            if (logTheMessage) {
                CorePlugin.logError(m_title + "\n" + m_msg, null);
            }
        }
    }

    private static boolean internalDialogHandler(Shell p_parent, String p_title, String p_msg,
            BPMessageTypes p_type, boolean p_showTechSupportContact) {

        booleanDialogResult = false;
        p_title = (p_title == null) ? "BridgePoint UML Suite" : p_title;
        if (p_showTechSupportContact) {
            p_msg = p_msg + "\n\n" + UIUtil.getTechSupportMessage();
        }

        if (CoreUtil.IsRunningHeadless) {
            p_parent = null;
        }

        Runnable dialog = new BPMessageDialog(p_parent, p_title, p_msg, p_type);
        if (p_parent != null || CoreUtil.IsRunningHeadless) {
            dialog.run();
        } else {
            PlatformUI.getWorkbench().getDisplay().syncExec(dialog);
        }
        return booleanDialogResult;
    }

    public static String getTechSupportMessage() {
        String msg = "Please visit the xtUML Forum for a searchable knowledgebase of technical issues,"
                + "the ability to open a service request online, and many other useful tools:\n\n"
                + "\thttps://www.xtuml.org/community/forum/xtuml-forum/\n";
        return msg;
    }

    /**
     * 
     * @param msg
     * @return true if the user responds yes and false if the user responds no
     */
    public static boolean displayYesNoQuestion(final String msg) {
        displayYesNoQuestion_isYes = true;

        if (CoreUtil.IsRunningHeadless) {
            displayYesNoQuestion_isYes = UIUtil.openMessageDialog(null, "BridgePoint UML Suite", null, msg,
                    UIUtil.BPMessageTypes.QUESTION, new String[] { "Yes", "No" }, 0); // yes is he default
        } else {
            PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() {

                public void run() {
                    org.eclipse.swt.widgets.Shell sh = PlatformUI.getWorkbench().getDisplay().getActiveShell();
                    MessageDialog dialog = new MessageDialog(sh, "BridgePoint UML Suite", null, msg,
                            MessageDialog.QUESTION, new String[] { "Yes", "No" }, 0); // yes is the default

                    displayYesNoQuestion_isYes = (dialog.open() == 0);
                }
            });
        }
        return displayYesNoQuestion_isYes;
    }

    /**
     * Mirror the functionality of the jface InputDialog.  If the user cancels
     * then dialog then false is returned.  If the users select OK, then 
     * true is returned, and the text entered is found in 
     * UIUtil.inputDialogResult.
     */
    public static String inputDialogResult = "";

    public static boolean inputDialog(Shell parentShell, String dialogTitle, String dialogMessage,
            String initialValue, IInputValidator validator) {
        inputDialogResult = "";
        if (CoreUtil.IsRunningHeadless) {
            outputTextForheadlessRun(BPMessageTypes.INPUT, dialogTitle, dialogMessage, initialValue);
        } else {
            InputDialog id = new InputDialog(parentShell, dialogTitle, dialogMessage, initialValue, validator);
            int result = id.open();
            id.getValue();
            if (result == InputDialog.OK) {
                inputDialogResult = id.getValue();
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    /**
     * A simple utility function that passes-along call to class RenameAction.
     * 
     * Returns null if the given name is valid for the given model element.
     * Otherwise, returns a message stating why the name is invalid.
     */
    public static String validateNameUsingRenameAction(String name, ModelElement element) {
        String result = RenameAction.isNameValid(name, element);
        if (result == null) {
            // if the element adapts to a file then we
            // must validate with the OS
            if (element instanceof NonRootModelElement) {
                NonRootModelElement nrme = (NonRootModelElement) element;
                if (PersistenceManager.getHierarchyMetaData().isComponentRoot(nrme)) {
                    IStatus validateName = RenameAction.validateName(nrme, name, IResource.FILE);
                    if (!validateName.isOK()) {
                        result = validateName.getMessage();
                    }
                }
            }
        }
        if (result != null && result.equals("")) {
            return null;
        }
        return result;
    }

    static class NameInputValidator implements IInputValidator {

        private ModelElement element;

        public NameInputValidator(ModelElement element) {
            this.element = element;
        }

        @Override
        public String isValid(String newText) {
            return validateNameUsingRenameAction(newText, element);
        }

    }

    public static IInputValidator newRenameValidator(ModelElement element) {
        return new NameInputValidator(element);
    }

    public static Object[] openSelectionDialog(Object[] objects, String message, String title) {
        if (CoreUtil.IsRunningHeadless) {
            return new Object[0];
        }
        UIUtil ui = new UIUtil();
        ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
                PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), new WorkbenchLabelProvider(),
                ui.new ProjectContentProvider(objects));
        dialog.setHelpAvailable(false);
        dialog.setInput(new Object());
        dialog.setMessage(message);
        dialog.setTitle(title);
        dialog.setAllowMultiple(true);
        dialog.setValidator(ui.new SelectionDialogValidator());

        int result = dialog.open();
        if (result == Dialog.OK) {
            return dialog.getResult();
        }
        return new Object[0];
    }

    class SelectionDialogValidator implements ISelectionStatusValidator {
        @Override
        public IStatus validate(Object[] selection) {
            if (selection.length == 0) {
                return new Status(IStatus.ERROR, CorePlugin.getName(), "");
            } else {
                return Status.CANCEL_STATUS;
            }
        }
    }

    class ProjectContentProvider implements ITreeContentProvider {
        Object[] projects;

        public ProjectContentProvider(Object[] projects) {
            this.projects = projects;
        }

        @Override
        public Object[] getChildren(Object parentElement) {
            if (parentElement instanceof IProject) {
                return new Object[0];
            } else {
                return projects;
            }
        }

        @Override
        public Object getParent(Object element) {
            return null;
        }

        @Override
        public boolean hasChildren(Object element) {
            return false;
        }

        @Override
        public Object[] getElements(Object inputElement) {
            if (inputElement instanceof IProject) {
                return new Object[0];
            } else {
                return projects;
            }
        }

        @Override
        public void dispose() {
            // nothing to do
        }

        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            // nothing to do
        }

    }
}