org.eclipse.oomph.setup.ui.wizards.ConfirmationPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.oomph.setup.ui.wizards.ConfirmationPage.java

Source

/*
 * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) 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:
 *    Eike Stepper - initial API and implementation
 */
package org.eclipse.oomph.setup.ui.wizards;

import org.eclipse.oomph.base.util.BaseUtil;
import org.eclipse.oomph.internal.setup.SetupProperties;
import org.eclipse.oomph.internal.ui.AccessUtil;
import org.eclipse.oomph.internal.ui.OomphAdapterFactoryContentProvider;
import org.eclipse.oomph.internal.ui.OomphDragAdapter;
import org.eclipse.oomph.internal.ui.OomphEditingDomain;
import org.eclipse.oomph.internal.ui.OomphTransferDelegate;
import org.eclipse.oomph.setup.CompoundTask;
import org.eclipse.oomph.setup.SetupTask;
import org.eclipse.oomph.setup.Trigger;
import org.eclipse.oomph.setup.User;
import org.eclipse.oomph.setup.Workspace;
import org.eclipse.oomph.setup.internal.core.SetupContext;
import org.eclipse.oomph.setup.internal.core.SetupTaskPerformer;
import org.eclipse.oomph.setup.ui.SetupUIPlugin;
import org.eclipse.oomph.ui.ButtonBar;
import org.eclipse.oomph.ui.ErrorDialog;
import org.eclipse.oomph.ui.PropertiesViewer;
import org.eclipse.oomph.ui.UIUtil;
import org.eclipse.oomph.util.OS;
import org.eclipse.oomph.util.ObjectUtil;
import org.eclipse.oomph.util.PropertiesUtil;
import org.eclipse.oomph.util.ReflectUtil;
import org.eclipse.oomph.util.StringUtil;

import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.command.BasicCommandStack;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IItemColorProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.emf.edit.ui.provider.ExtendedColorRegistry;

import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
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.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;

import java.io.File;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * @author Eike Stepper
 */
public class ConfirmationPage extends SetupWizardPage {
    private static final Object INPUT = new Object();

    private static final Object ROOT_ELEMENT = new Object();

    private CheckboxTreeViewer viewer;

    private TreeViewer childrenViewer;

    private PropertiesViewer propertiesViewer;

    private Button showAllButton;

    private Button offlineButton;

    private Boolean offlineProperty;

    private Button mirrorsButton;

    private Boolean mirrorsProperty;

    private Button overwriteButton;

    private File lastConfigurationLocation;

    private boolean configurationLocationExists;

    private Button switchWorkspaceButton;

    private File currentWorkspaceLocation;

    private File newWorkspaceLocation;

    private boolean someTaskChecked;

    private ControlAdapter columnResizer;

    private AdapterFactoryLabelProvider.ColorProvider labelProvider;

    private EditingDomain domain;

    public ConfirmationPage() {
        super("ConfirmationPage");
        setTitle("Confirmation");
        setDescription("Review the tasks to be executed and optionally uncheck unwanted tasks.");
    }

    @Override
    protected Control createUI(final Composite parent) {
        Composite mainComposite = new Composite(parent, SWT.NONE);
        mainComposite.setLayout(UIUtil.createGridLayout(1));

        SashForm horizontalSash = new SashForm(mainComposite, SWT.SMOOTH | SWT.HORIZONTAL);
        UIUtil.grabVertical(UIUtil.applyGridData(horizontalSash));
        AccessUtil.setKey(horizontalSash, "hsash");

        fillCheckPane(horizontalSash);

        SashForm verticalSash = new SashForm(horizontalSash, SWT.SMOOTH | SWT.VERTICAL);
        AccessUtil.setKey(verticalSash, "vsash");

        fillChildrenPane(verticalSash);

        propertiesViewer = new PropertiesViewer(verticalSash, SWT.BORDER);
        createContextMenu(propertiesViewer);
        addHelpCallout(propertiesViewer.getTable(), 3);

        connectMasterDetail(viewer, childrenViewer);
        connectMasterDetail(viewer, propertiesViewer);
        connectMasterDetail(childrenViewer, propertiesViewer);

        horizontalSash.setWeights(new int[] { 3, 2 });

        setPageComplete(true);
        return mainComposite;
    }

    @Override
    protected void createCheckButtons(ButtonBar buttonBar) {
        showAllButton = buttonBar.addCheckButton("Show all triggered tasks",
                "Show unneeded tasks in addition to the needed tasks", false, "showAll");
        showAllButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                viewer.refresh();

                if (showAllButton.getSelection()) {
                    viewer.setExpandedState(ROOT_ELEMENT, true);
                }
            }
        });
        AccessUtil.setKey(showAllButton, "showAllTasks");

        offlineProperty = PropertiesUtil.getBoolean(SetupProperties.PROP_SETUP_OFFLINE);
        if (offlineProperty == null) {
            offlineButton = buttonBar.addCheckButton("Offline",
                    "Avoid unnecessary network requests during the installation process", false,
                    "toggleCommand:org.eclipse.oomph.ui.ToggleOfflineMode");
            AccessUtil.setKey(offlineButton, "offline");
        }

        mirrorsProperty = PropertiesUtil.getBoolean(SetupProperties.PROP_SETUP_MIRRORS);
        if (mirrorsProperty == null) {
            mirrorsButton = buttonBar.addCheckButton("Mirrors",
                    "Make use of p2 mirrors during the installation process", true, "mirrors");
            AccessUtil.setKey(mirrorsButton, "mirrors");
        }

        if (getTrigger() == Trigger.BOOTSTRAP) {
            overwriteButton = buttonBar.addCheckButton("Overwrite",
                    "Rename the existing configuration folder during the installation process", false, null);
            overwriteButton.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    validate();
                }
            });
            AccessUtil.setKey(overwriteButton, "overwrite");
        } else if (getWorkspace() != null) {
            switchWorkspaceButton = buttonBar.addCheckButton("Switch workspace", "Switch to a different workspace",
                    false, null);
            switchWorkspaceButton.addSelectionListener(new SelectionAdapter() {
                @Override
                public void widgetSelected(SelectionEvent e) {
                    validate();
                }
            });
            AccessUtil.setKey(switchWorkspaceButton, "switch");
        }
    }

    @Override
    public void enterPage(final boolean forward) {
        if (forward) {
            initNeededSetupTasks();

            SetupTaskPerformer performer = getPerformer();
            viewer.setInput(INPUT);
            viewer.setSubtreeChecked(ROOT_ELEMENT, true);
            someTaskChecked = performer.getTriggeredSetupTasks().size() > 0;

            checkOverwrite();

            if (switchWorkspaceButton != null) {
                newWorkspaceLocation = performer.getWorkspaceLocation();
                URI currentWorkspaceLocationURI = CommonPlugin
                        .resolve(URI.createURI(Platform.getInstanceLocation().getURL().toString()));
                if (currentWorkspaceLocationURI.isFile()) {
                    currentWorkspaceLocation = new File(currentWorkspaceLocationURI.toFileString());
                    boolean workspaceLocationChanged = newWorkspaceLocation != null
                            && !newWorkspaceLocation.equals(currentWorkspaceLocation);
                    switchWorkspaceButton.setVisible(workspaceLocationChanged);
                    viewer.getControl().setEnabled(!workspaceLocationChanged);
                }
            }

            validate();

            if (getTrigger() == Trigger.STARTUP || performer.isSkipConfirmation()) {
                gotoNextPage();
            }
        } else {
            Set<URI> checkedElements = new HashSet<URI>();
            SetupTaskPerformer performer = getPerformer();
            for (SetupTask setupTask : performer.getTriggeredSetupTasks()) {
                if (viewer.getChecked(setupTask)) {
                    checkedElements.add(EcoreUtil.getURI(setupTask));
                }
            }

            boolean hasSuccessfullyPerformed = performer.hasSuccessfullyPerformed();

            SetupWizardPage promptPage = (SetupWizardPage) getPreviousPage();
            promptPage.enterPage(false);
            promptPage.leavePage(true);

            initNeededSetupTasks();

            viewer.refresh();

            for (SetupTask setupTask : getPerformer().getTriggeredSetupTasks()) {
                if (checkedElements.contains(EcoreUtil.getURI(setupTask))) {
                    viewer.setChecked(setupTask, true);
                }
            }

            if (hasSuccessfullyPerformed) {
                lastConfigurationLocation = null;
                checkOverwrite();
            } else if (overwriteButton != null) {
                // If we've not successfully perform and we try to perform for the current configuration location again, we'll want to overwrite it.
                overwriteButton.setSelection(true);
            }

            updateCheckStates();
        }

        viewer.expandAll();
    }

    private void checkOverwrite() {
        if (overwriteButton != null) {
            File configurationLocation = getPerformer().getProductConfigurationLocation();
            if (!ObjectUtil.equals(configurationLocation, lastConfigurationLocation)) {
                overwriteButton.setSelection(false);
                lastConfigurationLocation = configurationLocation;
            }

            configurationLocationExists = configurationLocation.exists();
            overwriteButton.setVisible(configurationLocationExists);
        }
    }

    private void initNeededSetupTasks() {
        try {
            getPerformer().initNeededSetupTasks(new NullProgressMonitor());
        } catch (final Exception ex) {
            UIUtil.asyncExec(new Runnable() {
                public void run() {
                    ErrorDialog.open(ex);
                }
            });
        }
    }

    @Override
    public void leavePage(boolean forward) {
        if (forward) {
            if (switchWorkspaceButton != null && switchWorkspaceButton.getSelection()) {
                try {
                    Class<?> openWorkspaceActionClass = CommonPlugin.loadClass("org.eclipse.ui.ide",
                            "org.eclipse.ui.internal.ide.actions.OpenWorkspaceAction");
                    Class<?> chooseWorkspaceDataClass = CommonPlugin.loadClass("org.eclipse.ui.ide",
                            "org.eclipse.ui.internal.ide.ChooseWorkspaceData");
                    Constructor<?> chooseWorkspaceDataConstructor = ReflectUtil
                            .getConstructor(chooseWorkspaceDataClass, String.class);
                    Object chooseWorkspaceData = chooseWorkspaceDataConstructor
                            .newInstance(currentWorkspaceLocation.toString());

                    Object openWorkspaceAction = openWorkspaceActionClass.getConstructors()[0]
                            .newInstance(PlatformUI.getWorkbench().getActiveWorkbenchWindow());
                    Class<?>[] declaredClasses = openWorkspaceActionClass.getDeclaredClasses();
                    for (Class<?> declaredClass : declaredClasses) {
                        if ("WorkspaceMRUAction".equals(declaredClass.getSimpleName())) {
                            Constructor<?> workspaceMRUActionConstructor = ReflectUtil.getConstructor(declaredClass,
                                    openWorkspaceActionClass, String.class, chooseWorkspaceDataClass);
                            Action workspaceMRUAction = (Action) workspaceMRUActionConstructor.newInstance(
                                    openWorkspaceAction, newWorkspaceLocation.toString(), chooseWorkspaceData);
                            saveLocalFiles(getPerformer());
                            workspaceMRUAction.run();
                            getWizard().performCancel();
                            break;
                        }
                    }
                } catch (Exception ex) {
                    SetupUIPlugin.INSTANCE.log(ex);
                    ErrorDialog.open(ex);
                }
            } else {
                EList<SetupTask> neededSetupTasks = null;

                try {
                    SetupTaskPerformer performer = getPerformer();
                    performer.setMirrors(isMirrors());
                    performer.setOffline(isOffline());

                    Set<SetupTask> checkedTasks = getCheckedTasks();

                    neededSetupTasks = performer.initNeededSetupTasks(new NullProgressMonitor());
                    neededSetupTasks.retainAll(checkedTasks);
                } catch (Exception ex) {
                    if (neededSetupTasks != null) {
                        neededSetupTasks.clear();
                    }

                    SetupUIPlugin.INSTANCE.log(ex);
                    ErrorDialog.open(ex);
                }
            }
        }
    }

    private void saveLocalFiles(SetupTaskPerformer performer) throws Exception {
        // Get the user with the recorded changes and the original user.
        User user = getUser();
        User originalUser = SetupContext.createUserOnly(getResourceSet()).getUser();

        // Get the workspace with the changes and copy it.
        Workspace workspace = getWorkspace();
        Workspace copiedWorkspace = EcoreUtil.copy(workspace);

        // Find the compound task with the recorded changes.
        CompoundTask workspaceRestrictedCompoundTask = null;
        for (Iterator<EObject> it = user.eAllContents(); it.hasNext();) {
            EObject eObject = it.next();
            if (eObject instanceof CompoundTask) {
                CompoundTask compoundTask = (CompoundTask) eObject;
                if (compoundTask.getRestrictions().contains(workspace)) {
                    // Make a copy of it.
                    workspaceRestrictedCompoundTask = EcoreUtil.copy(compoundTask);
                    break;
                }
            }
        }

        // If we can't find it, something is seriously wrong.
        if (workspaceRestrictedCompoundTask == null) {
            throw new Exception("Workspace compound task could not be found");
        }

        // Put the workspace copy in a resource at the right location and save it.
        URI workspaceResourceURI = URI.createFileURI(new File(performer.getWorkspaceLocation(),
                ".metadata/.plugins/org.eclipse.oomph.setup/workspace.setup").toString());
        Resource workspaceResource = getResourceSet().getResourceFactoryRegistry().getFactory(workspaceResourceURI)
                .createResource(workspaceResourceURI);
        workspaceResource.getContents().add(copiedWorkspace);
        BaseUtil.saveEObject(copiedWorkspace);

        // Change the restriction to be restricted to the new workspace copy.
        workspaceRestrictedCompoundTask.getRestrictions().clear();
        workspaceRestrictedCompoundTask.getRestrictions().add(copiedWorkspace);
        workspaceRestrictedCompoundTask.setName(labelProvider.getText(copiedWorkspace));

        // Add the restricted compound task to the original user, and save it.
        originalUser.getSetupTasks().add(workspaceRestrictedCompoundTask);
        BaseUtil.saveEObject(originalUser);
    }

    private void fillCheckPane(Composite parent) {
        viewer = new CheckboxTreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        createContextMenu(viewer);

        final Tree tree = viewer.getTree();
        tree.setLayoutData(new GridData(GridData.FILL_BOTH));
        addHelpCallout(tree, 1);

        viewer.setContentProvider(new ITreeContentProvider() {
            public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            }

            public void dispose() {
            }

            public boolean hasChildren(Object element) {
                return element == ConfirmationPage.this || element == ROOT_ELEMENT;
            }

            public Object getParent(Object element) {
                if (element instanceof SetupTask) {
                    return ROOT_ELEMENT;
                }

                if (element == ROOT_ELEMENT) {
                    return INPUT;
                }

                return null;
            }

            public Object[] getElements(Object element) {
                return getChildren(element);
            }

            public Object[] getChildren(Object element) {
                List<Object> children = new ArrayList<Object>();

                if (element == INPUT) {
                    children.add(ROOT_ELEMENT);
                } else if (element == ROOT_ELEMENT) {
                    children.addAll(isShowAll() ? getPerformer().getTriggeredSetupTasks()
                            : getPerformer().getNeededTasks());
                }

                return children.toArray();
            }
        });

        final Control viewerControl = viewer.getControl();
        final Color normalForeground = viewerControl.getForeground();
        Color normalBackground = viewerControl.getBackground();
        final Color disabledForeground = ExtendedColorRegistry.INSTANCE.getColor(normalForeground, normalBackground,
                IItemColorProvider.GRAYED_OUT_COLOR);
        AdapterFactory adapterFactory = getAdapterFactory();
        labelProvider = new AdapterFactoryLabelProvider.ColorProvider(adapterFactory, normalForeground,
                normalBackground) {
            @Override
            public String getText(Object object) {
                if (object == ROOT_ELEMENT) {
                    Trigger trigger = getTrigger();
                    return StringUtil.cap(getText(trigger).toLowerCase()) + " Tasks";
                }

                return super.getText(object);
            }

            @Override
            public Image getImage(Object object) {
                if (object == ROOT_ELEMENT) {
                    Trigger trigger = getTrigger();
                    String key = StringUtil.cap(trigger.toString().toLowerCase()) + "Trigger";
                    return SetupUIPlugin.INSTANCE.getSWTImage(key);
                }

                return super.getImage(object);
            }

            @Override
            public Color getForeground(Object object) {
                return !(object instanceof SetupTask) || getPerformer().getNeededTasks().contains(object)
                        ? viewerControl.getForeground()
                        : disabledForeground;
            }
        };
        viewer.setLabelProvider(labelProvider);

        viewer.addCheckStateListener(new ICheckStateListener() {
            public void checkStateChanged(CheckStateChangedEvent event) {
                boolean checked = event.getChecked();

                final Object element = event.getElement();
                if (element == ROOT_ELEMENT) {
                    viewer.setSubtreeChecked(ROOT_ELEMENT, checked);
                }

                updateCheckStates();
            }
        });

        viewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                Object element = ((IStructuredSelection) event.getSelection()).getFirstElement();
                if (element == ROOT_ELEMENT) {
                    viewer.setExpandedState(ROOT_ELEMENT, !viewer.getExpandedState(ROOT_ELEMENT));
                } else {
                    viewer.setCheckedElements(new Object[] { element });
                    updateCheckStates();
                }
            }
        });
    }

    private void createContextMenu(final StructuredViewer viewer) {
        if (domain == null) {
            domain = new OomphEditingDomain(getAdapterFactory(), new BasicCommandStack(),
                    new HashMap<Resource, Boolean>(), OomphTransferDelegate.DELEGATES);
        }

        final ISelectionProvider selectionProvider = new ISelectionProvider() {
            public ISelection getSelection() {
                Object[] selection = ((IStructuredSelection) viewer.getSelection()).toArray();
                for (int i = 0; i < selection.length; ++i) {
                    Object object = selection[i];
                    if (object instanceof Object[]) {
                        selection[i] = ((Object[]) object)[1];
                    }
                }
                return new StructuredSelection(selection);
            }

            public void setSelection(ISelection selection) {
            }

            public void removeSelectionChangedListener(ISelectionChangedListener listener) {
                // Ignore
            }

            public void addSelectionChangedListener(ISelectionChangedListener listener) {
            }
        };

        MenuManager contextMenu = new MenuManager("#PopUp");
        contextMenu.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                final IStructuredSelection selection = (IStructuredSelection) selectionProvider.getSelection();
                Action copy = new Action("Copy") {
                    @SuppressWarnings("unchecked")
                    @Override
                    public void run() {
                        domain.setClipboard(selection.toList());
                    }
                };
                copy.setEnabled(!selection.isEmpty());
                copy.setAccelerator((OS.INSTANCE.isMac() ? SWT.COMMAND : SWT.CTRL) | 'C');
                manager.add(copy);
            }
        });
        contextMenu.setRemoveAllWhenShown(true);
        Control control = viewer.getControl();
        control.addKeyListener(new KeyAdapter() {
            @SuppressWarnings("unchecked")
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.keyCode == 'c' && (e.stateMask & SWT.MODIFIER_MASK
                        & (OS.INSTANCE.isMac() ? SWT.COMMAND : SWT.CTRL)) != 0) {
                    final IStructuredSelection selection = (IStructuredSelection) selectionProvider.getSelection();
                    if (!selection.isEmpty()) {
                        domain.setClipboard(selection.toList());
                    }

                    e.doit = false;
                }
            }
        });
        Menu menu = contextMenu.createContextMenu(control);
        control.setMenu(menu);

        int dndOperations = DND.DROP_COPY;
        List<? extends Transfer> transfersList = OomphTransferDelegate.asTransfers(OomphTransferDelegate.DELEGATES);
        Transfer[] transfers = transfersList.toArray(new Transfer[transfersList.size()]);
        viewer.addDragSupport(dndOperations, transfers,
                new OomphDragAdapter(domain, selectionProvider, OomphTransferDelegate.DELEGATES));
    }

    private void fillChildrenPane(SashForm verticalSash) {
        childrenViewer = new TreeViewer(verticalSash, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
        createContextMenu(childrenViewer);
        AdapterFactory adapterFactory = getAdapterFactory();
        childrenViewer.setLabelProvider(new AdapterFactoryLabelProvider(adapterFactory));
        childrenViewer.setContentProvider(new OomphAdapterFactoryContentProvider(adapterFactory) {
            @Override
            public Object[] getElements(Object object) {
                List<Object> result = new ArrayList<Object>();
                for (Object child : super.getElements(object)) {
                    if (!(child instanceof SetupTask)) {
                        result.add(child);
                    }
                }

                return result.toArray();
            }
        });

        final Tree tree = childrenViewer.getTree();
        tree.setHeaderVisible(true);
        addHelpCallout(tree, 2);

        final TreeColumn column = new TreeColumn(tree, SWT.NONE);
        column.setText("Nested Elements");
        columnResizer = new ControlAdapter() {
            @Override
            public void controlResized(ControlEvent e) {
                if (!tree.isDisposed()) {
                    try {
                        tree.setRedraw(false);

                        Rectangle clientArea = tree.getClientArea();
                        int clientWidth = clientArea.width - clientArea.x;

                        // We get events during setInput where the tree items are disposed because the view is empty and then the column can't be packed.
                        TreeItem[] items = tree.getItems();
                        if (items.length > 0 && !items[0].isDisposed()) {
                            column.pack();
                            int width = column.getWidth();
                            if (width < clientWidth) {
                                column.setWidth(clientWidth);
                            }
                        } else {
                            column.setWidth(clientWidth);
                        }

                    } finally {
                        tree.setRedraw(true);
                    }
                }
            }
        };

        tree.addControlListener(columnResizer);
        tree.getDisplay().asyncExec(new Runnable() {
            public void run() {
                columnResizer.controlResized(null);
            }
        });

        childrenViewer.setInput(new Object());
    }

    private void connectMasterDetail(final TreeViewer master, final Viewer detail) {
        master.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                if (detail != null) {
                    Object selection = ((IStructuredSelection) master.getSelection()).getFirstElement();
                    Control control = detail.getControl();
                    try {
                        control.setRedraw(false);
                        detail.setInput(selection);
                        columnResizer.controlResized(null);
                    } finally {
                        control.setRedraw(true);
                    }
                }
            }
        });
    }

    private Set<SetupTask> getCheckedTasks() {
        Set<SetupTask> tasks = new HashSet<SetupTask>();
        for (Object object : viewer.getCheckedElements()) {
            if (object instanceof SetupTask) {
                SetupTask task = (SetupTask) object;
                tasks.add(task);
            }
        }

        return tasks;
    }

    private void updateCheckStates() {
        Set<SetupTask> checkedTasks = getCheckedTasks();
        int checked = checkedTasks.size();

        EList<SetupTask> allTasks = isShowAll() ? getPerformer().getTriggeredSetupTasks()
                : getPerformer().getNeededTasks();
        int all = allTasks.size();

        viewer.setChecked(ROOT_ELEMENT, checked == all);

        checkedTasks.retainAll(getPerformer().getNeededTasks());
        someTaskChecked = !checkedTasks.isEmpty();

        validate();
    }

    private void validate() {
        setErrorMessage(null);
        setPageComplete(false);

        if (switchWorkspaceButton != null && switchWorkspaceButton.isVisible()
                && switchWorkspaceButton.getSelection()) {
            setMessage("The IDE will be restarted with the new workspace " + getPerformer().getWorkspaceLocation()
                    + ".", IMessageProvider.WARNING);
        } else {
            setMessage(null);
        }

        if (!someTaskChecked) {
            if (getWizard().getPerformer().getNeededTasks().size() == 0) {
                setMessage("No tasks need to perform.", IMessageProvider.WARNING);
            } else {
                setErrorMessage("Please check one or more tasks to continue with the installation process.");
            }

            return;
        }

        if (configurationLocationExists && !overwriteButton.getSelection()) {
            setErrorMessage("The folder " + lastConfigurationLocation
                    + " exists.\n Please check the Overwrite button to rename it and continue with the installation process.");
            return;
        } else if (newWorkspaceLocation != null
                && !ObjectUtil.equals(newWorkspaceLocation, currentWorkspaceLocation)
                && !switchWorkspaceButton.getSelection()) {
            setErrorMessage("The workspace location is changed to " + getPerformer().getWorkspaceLocation()
                    + ".  Please check the 'Switch workspace' button to restarted the IDE, switch to the new workspace, and continue the installation process.");
            return;
        }

        setPageComplete(true);
        setButtonState(IDialogConstants.NEXT_ID, false);
    }

    private boolean isShowAll() {
        return showAllButton.getSelection();
    }

    private boolean isOffline() {
        return getProperty(SetupProperties.PROP_SETUP_OFFLINE_STARTUP, offlineProperty, offlineButton);
    }

    private boolean isMirrors() {
        return getProperty(SetupProperties.PROP_SETUP_MIRRORS_STARTUP, mirrorsProperty, mirrorsButton);
    }

    public static boolean getProperty(String propertyKey, Boolean property, final Button button) {
        if (PropertiesUtil.isProperty(propertyKey)) {
            return true;
        }

        if (property != null) {
            return property;
        }

        final boolean[] result = { false };
        UIUtil.syncExec(new Runnable() {
            public void run() {
                result[0] = button.getSelection();
            }
        });

        return result[0];
    }
}