org.eclipse.dltk.internal.ui.wizards.buildpath.VariableBlock.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.dltk.internal.ui.wizards.buildpath.VariableBlock.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2008 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.dltk.internal.ui.wizards.buildpath;

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

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.*;
import org.eclipse.dltk.core.*;
import org.eclipse.dltk.internal.ui.util.CoreUtility;
import org.eclipse.dltk.internal.ui.wizards.NewWizardMessages;
import org.eclipse.dltk.internal.ui.wizards.dialogfields.*;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.util.ExceptionHandler;
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.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.StructuredSelection;
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();

        BPVariableElementLabelProvider labelProvider = new BPVariableElementLabelProvider(inPreferencePage);

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

        fVariablesList.enableButton(1, false);

        // TODO: create a sorter or modify ListDialogField to work with
        // comparators
        // fVariablesList.setViewerComparator(new ViewerComparator() {
        // public int compare(Viewer viewer, Object e1, Object e2) {
        // if (e1 instanceof BPVariableElement
        // && e2 instanceof BPVariableElement) {
        // return getComparator().compare(
        // ((BPVariableElement) e1).getName(),
        // ((BPVariableElement) 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;

        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 DLTKUIPlugin.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((BPVariableElement) 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((BPVariableElement) selected.get(0));
                }
            }
        }

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

        public void dialogFieldChanged(DialogField field) {
        }

    }

    private boolean containsReadOnly(List selected) {
        for (int i = selected.size() - 1; i >= 0; i--) {
            if (((BPVariableElement) 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;
    }

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

        VariableCreationDialog dialog = new VariableCreationDialog(getShell(), entry, existingEntries);
        if (dialog.open() != Window.OK) {
            return;
        }
        BPVariableElement newEntry = dialog.getBuildpathElement();
        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(DLTKCore.getBuildpathVariableNames()));

        // remove all unchanged
        List changedElements = fVariablesList.getElements();
        for (int i = changedElements.size() - 1; i >= 0; i--) {
            BPVariableElement curr = (BPVariableElement) changedElements.get(i);
            if (curr.isReadOnly()) {
                changedElements.remove(curr);
            } else {
                IPath path = curr.getPath();
                IPath prevPath = DLTKCore.getBuildpathVariable(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 {
            IScriptModel model = DLTKCore.create(ResourcesPlugin.getWorkspace().getRoot());
            IScriptProject[] projects = model.getScriptProjects();
            for (int i = 0; i < projects.length; i++) {
                IBuildpathEntry[] entries = projects[i].getRawBuildpath();
                for (int k = 0; k < entries.length; k++) {
                    IBuildpathEntry curr = entries[k];
                    if (curr.getEntryKind() == IBuildpathEntry.BPE_VARIABLE) {
                        String var = curr.getPath().segment(0);
                        if (removed.contains(var) || changed.contains(var)) {
                            return true;
                        }
                    }
                }
            }
        } catch (ModelException 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 ModelException, 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++) {
                BPVariableElement curr = (BPVariableElement) 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++;
            }
            DLTKCore.setBuildpathVariables(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) {
        BPVariableElement initSelectedElement = null;

        String[] entries = DLTKCore.getBuildpathVariableNames();
        ArrayList elements = new ArrayList(entries.length);
        for (int i = 0; i < entries.length; i++) {
            String name = entries[i];
            BPVariableElement elem;
            IPath entryPath = DLTKCore.getBuildpathVariable(name);
            if (entryPath != null) {
                elem = new BPVariableElement(name, entryPath);
                elements.add(elem);
                if (name.equals(initSelection)) {
                    initSelectedElement = elem;
                }
            } else {
                DLTKUIPlugin.logErrorMessage("VariableBlock: Buildpath 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++) {
            BPVariableElement elem = (BPVariableElement) fVariablesList.getElement(i);
            if (elem.getName().equals(elementName)) {
                fVariablesList.selectElements(new StructuredSelection(elem));
                return;
            }
        }
    }

}