org.eclipse.edt.ide.ui.internal.property.pages.VariableBlock.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.edt.ide.ui.internal.property.pages.VariableBlock.java

Source

/*******************************************************************************
 * Copyright  2009, 2013 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 *
 *******************************************************************************/
package org.eclipse.edt.ide.ui.internal.property.pages;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.util.CoreUtility;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.ui.wizards.NewWizardMessages;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.IListAdapter;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.LayoutUtil;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.ListDialogField;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

public class VariableBlock {

    private final ListDialogField fVariablesList;
    private Control fControl;
    private CLabel fWarning;
    private boolean fHasChanges;

    private List fSelectedElements;
    private boolean fAskToBuild;
    private final boolean fEditOnDoubleclick;

    public VariableBlock(boolean inPreferencePage, String initSelection) {

        fSelectedElements = new ArrayList(0);
        fEditOnDoubleclick = inPreferencePage;
        fAskToBuild = true;

        String[] buttonLabels = new String[] { NewWizardMessages.VariableBlock_vars_add_button,
                NewWizardMessages.VariableBlock_vars_edit_button,
                NewWizardMessages.VariableBlock_vars_remove_button };

        VariablesAdapter adapter = new VariablesAdapter();

        CPVariableElementLabelProvider labelProvider = new CPVariableElementLabelProvider(inPreferencePage);

        fVariablesList = new ListDialogField(adapter, buttonLabels, labelProvider);
        fVariablesList.setDialogFieldListener(adapter);
        fVariablesList.setLabelText(NewWizardMessages.VariableBlock_vars_label);
        fVariablesList.setRemoveButtonIndex(2);

        fVariablesList.enableButton(1, false);

        fVariablesList.setViewerComparator(new ViewerComparator() {
            public int compare(Viewer viewer, Object e1, Object e2) {
                if (e1 instanceof CPVariableElement && e2 instanceof CPVariableElement) {
                    return getComparator().compare(((CPVariableElement) e1).getName(),
                            ((CPVariableElement) e2).getName());
                }
                return super.compare(viewer, e1, e2);
            }
        });
        refresh(initSelection);
    }

    public boolean hasChanges() {
        return fHasChanges;
    }

    public void setChanges(boolean hasChanges) {
        fHasChanges = hasChanges;
    }

    public Control createContents(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        composite.setFont(parent.getFont());

        LayoutUtil.doDefaultLayout(composite, new DialogField[] { fVariablesList }, true, 0, 0);
        LayoutUtil.setHorizontalGrabbing(fVariablesList.getListControl(null));

        fWarning = new CLabel(composite, SWT.NONE);
        fWarning.setLayoutData(
                new GridData(SWT.FILL, SWT.TOP, true, false, fVariablesList.getNumberOfControls() - 1, 1));

        fControl = composite;
        updateDeprecationWarning();

        return composite;
    }

    public void addDoubleClickListener(IDoubleClickListener listener) {
        fVariablesList.getTableViewer().addDoubleClickListener(listener);
    }

    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        fVariablesList.getTableViewer().addSelectionChangedListener(listener);
    }

    private Shell getShell() {
        if (fControl != null) {
            return fControl.getShell();
        }
        return JavaPlugin.getActiveWorkbenchShell();
    }

    private class VariablesAdapter implements IDialogFieldListener, IListAdapter {

        // -------- IListAdapter --------

        public void customButtonPressed(ListDialogField field, int index) {
            switch (index) {
            case 0: /* add */
                editEntries(null);
                break;
            case 1: /* edit */
                List selected = field.getSelectedElements();
                editEntries((CPVariableElement) selected.get(0));
                break;
            }
        }

        public void selectionChanged(ListDialogField field) {
            doSelectionChanged(field);
        }

        public void doubleClicked(ListDialogField field) {
            if (fEditOnDoubleclick) {
                List selected = field.getSelectedElements();
                if (canEdit(selected, containsReadOnly(selected))) {
                    editEntries((CPVariableElement) selected.get(0));
                }
            }
        }

        // ---------- IDialogFieldListener --------

        public void dialogFieldChanged(DialogField field) {
        }

    }

    private boolean containsReadOnly(List selected) {
        for (int i = selected.size() - 1; i >= 0; i--) {
            if (((CPVariableElement) selected.get(i)).isReadOnly()) {
                return true;
            }
        }
        return false;
    }

    private boolean canEdit(List selected, boolean containsReadOnly) {
        return selected.size() == 1 && !containsReadOnly;
    }

    /**
     * @param field the dialog field 
     */
    private void doSelectionChanged(DialogField field) {
        List selected = fVariablesList.getSelectedElements();
        boolean containsReadOnly = containsReadOnly(selected);

        // edit
        fVariablesList.enableButton(1, canEdit(selected, containsReadOnly));
        // remove button
        fVariablesList.enableButton(2, !containsReadOnly);

        fSelectedElements = selected;
        updateDeprecationWarning();
    }

    private void updateDeprecationWarning() {
        if (fWarning == null || fWarning.isDisposed())
            return;

        for (Iterator iter = fSelectedElements.iterator(); iter.hasNext();) {
            CPVariableElement element = (CPVariableElement) iter.next();
            String deprecationMessage = element.getDeprecationMessage();
            if (deprecationMessage != null) {
                fWarning.setText(deprecationMessage);
                fWarning.setImage(JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING));
                return;
            }
        }
        fWarning.setText(null);
        fWarning.setImage(null);
    }

    private void editEntries(CPVariableElement entry) {
        List existingEntries = fVariablesList.getElements();

        VariableCreationDialog dialog = new VariableCreationDialog(getShell(), entry, existingEntries);
        if (dialog.open() != Window.OK) {
            return;
        }
        CPVariableElement newEntry = dialog.getClasspathElement();
        if (entry == null) {
            fVariablesList.addElement(newEntry);
            entry = newEntry;
            fHasChanges = true;
        } else {
            boolean hasChanges = !(entry.getName().equals(newEntry.getName())
                    && entry.getPath().equals(newEntry.getPath()));
            if (hasChanges) {
                fHasChanges = true;
                entry.setName(newEntry.getName());
                entry.setPath(newEntry.getPath());
                fVariablesList.refresh();
            }
        }
        fVariablesList.selectElements(new StructuredSelection(entry));
    }

    public List getSelectedElements() {
        return fSelectedElements;
    }

    public boolean performOk() {
        ArrayList removedVariables = new ArrayList();
        ArrayList changedVariables = new ArrayList();
        removedVariables.addAll(Arrays.asList(JavaCore.getClasspathVariableNames()));

        // remove all unchanged
        List changedElements = fVariablesList.getElements();
        for (int i = changedElements.size() - 1; i >= 0; i--) {
            CPVariableElement curr = (CPVariableElement) changedElements.get(i);
            if (curr.isReadOnly()) {
                changedElements.remove(curr);
            } else {
                IPath path = curr.getPath();
                IPath prevPath = JavaCore.getClasspathVariable(curr.getName());
                if (prevPath != null && prevPath.equals(path)) {
                    changedElements.remove(curr);
                } else {
                    changedVariables.add(curr.getName());
                }
            }
            removedVariables.remove(curr.getName());
        }
        int steps = changedElements.size() + removedVariables.size();
        if (steps > 0) {

            boolean needsBuild = false;
            if (fAskToBuild && doesChangeRequireFullBuild(removedVariables, changedVariables)) {
                String title = NewWizardMessages.VariableBlock_needsbuild_title;
                String message = NewWizardMessages.VariableBlock_needsbuild_message;

                MessageDialog buildDialog = new MessageDialog(getShell(), title, null, message,
                        MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL,
                                IDialogConstants.NO_LABEL, IDialogConstants.CANCEL_LABEL },
                        2);
                int res = buildDialog.open();
                if (res != 0 && res != 1) {
                    return false;
                }
                needsBuild = (res == 0);
            }

            final VariableBlockRunnable runnable = new VariableBlockRunnable(removedVariables, changedElements);
            final ProgressMonitorDialog dialog = new ProgressMonitorDialog(getShell());
            try {
                dialog.run(true, true, runnable);
            } catch (InvocationTargetException e) {
                ExceptionHandler.handle(new InvocationTargetException(new NullPointerException()), getShell(),
                        NewWizardMessages.VariableBlock_variableSettingError_titel,
                        NewWizardMessages.VariableBlock_variableSettingError_message);
                return false;
            } catch (InterruptedException e) {
                return false;
            }

            if (needsBuild) {
                CoreUtility.getBuildJob(null).schedule();
            }
        }
        return true;
    }

    private boolean doesChangeRequireFullBuild(List removed, List changed) {
        try {
            IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot());
            IJavaProject[] projects = model.getJavaProjects();
            for (int i = 0; i < projects.length; i++) {
                IClasspathEntry[] entries = projects[i].getRawClasspath();
                for (int k = 0; k < entries.length; k++) {
                    IClasspathEntry curr = entries[k];
                    if (curr.getEntryKind() == IClasspathEntry.CPE_VARIABLE) {
                        String var = curr.getPath().segment(0);
                        if (removed.contains(var) || changed.contains(var)) {
                            return true;
                        }
                    }
                }
            }
        } catch (JavaModelException e) {
            return true;
        }
        return false;
    }

    private class VariableBlockRunnable implements IRunnableWithProgress {
        private final List fToRemove;
        private final List fToChange;

        public VariableBlockRunnable(List toRemove, List toChange) {
            fToRemove = toRemove;
            fToChange = toChange;
        }

        /*
          * @see IRunnableWithProgress#run(IProgressMonitor)
         */
        public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
            monitor.beginTask(NewWizardMessages.VariableBlock_operation_desc, 1);
            try {
                setVariables(monitor);

            } catch (CoreException e) {
                throw new InvocationTargetException(e);
            } catch (OperationCanceledException e) {
                throw new InterruptedException();
            } finally {
                monitor.done();
            }
        }

        public void setVariables(IProgressMonitor monitor) throws JavaModelException, CoreException {
            int nVariables = fToChange.size() + fToRemove.size();

            String[] names = new String[nVariables];
            IPath[] paths = new IPath[nVariables];
            int k = 0;

            for (int i = 0; i < fToChange.size(); i++) {
                CPVariableElement curr = (CPVariableElement) fToChange.get(i);
                names[k] = curr.getName();
                paths[k] = curr.getPath();
                k++;
            }
            for (int i = 0; i < fToRemove.size(); i++) {
                names[k] = (String) fToRemove.get(i);
                paths[k] = null;
                k++;
            }
            JavaCore.setClasspathVariables(names, paths, new SubProgressMonitor(monitor, 1));
        }
    }

    /**
     * If set to true, a dialog will ask the user to build on variable changed
     * @param askToBuild The askToBuild to set
     */
    public void setAskToBuild(boolean askToBuild) {
        fAskToBuild = askToBuild;
    }

    /**
     * @param initSelection the initial selection
     */
    public void refresh(String initSelection) {
        CPVariableElement initSelectedElement = null;

        String[] entries = JavaCore.getClasspathVariableNames();
        ArrayList elements = new ArrayList(entries.length);
        for (int i = 0; i < entries.length; i++) {
            String name = entries[i];
            CPVariableElement elem;
            IPath entryPath = JavaCore.getClasspathVariable(name);
            if (entryPath != null) {
                elem = new CPVariableElement(name, entryPath);
                elements.add(elem);
                if (name.equals(initSelection)) {
                    initSelectedElement = elem;
                }
            } else {
                JavaPlugin.logErrorMessage("VariableBlock: Classpath variable with null value: " + name); //$NON-NLS-1$
            }
        }

        fVariablesList.setElements(elements);

        if (initSelectedElement != null) {
            ISelection sel = new StructuredSelection(initSelectedElement);
            fVariablesList.selectElements(sel);
        } else {
            fVariablesList.selectFirstElement();
        }

        fHasChanges = false;
    }

    public void setSelection(String elementName) {
        for (int i = 0; i < fVariablesList.getSize(); i++) {
            CPVariableElement elem = (CPVariableElement) fVariablesList.getElement(i);
            if (elem.getName().equals(elementName)) {
                fVariablesList.selectElements(new StructuredSelection(elem));
                return;
            }
        }
    }

}