edu.buffalo.cse.green.dialogs.NewElementWizard.java Source code

Java tutorial

Introduction

Here is the source code for edu.buffalo.cse.green.dialogs.NewElementWizard.java

Source

/* This file is part of Green.
 *
 * Copyright (C) 2005 The Research Foundation of State University of New York
 * All Rights Under Copyright Reserved, The Research Foundation of S.U.N.Y.
 * 
 * Green is free software, licensed under the terms of the Eclipse
 * Public License, version 1.0.  The license is available at
 * http://www.eclipse.org/legal/epl-v10.html
 */

package edu.buffalo.cse.green.dialogs;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.wizards.NewElementWizardPage;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;

import edu.buffalo.cse.green.GreenException;
import edu.buffalo.cse.green.PlugIn;
import edu.buffalo.cse.green.editor.model.CompartmentModel;
import edu.buffalo.cse.green.editor.model.MemberModel;
import edu.buffalo.cse.green.editor.model.RootModel;
import edu.buffalo.cse.green.editor.model.filters.MemberVisibility;
import static edu.buffalo.cse.green.preferences.VariableAffix.*;
import edu.buffalo.cse.green.preferences.VariableAffix;

/**
 * Opens a dialog box that prompts the user for a new element that will be
 * displayed in the diagram.
 * 
 * @author bcmartin
 */
public abstract class NewElementWizard extends GreenWizard implements INewWizard {
    private IWorkbench _workbench;

    private IStructuredSelection _selection;

    protected NewTypeWizardPage _fPage;

    private static final String DEFAULT_PACKAGE_ERROR = "Cannot use default package to create type in editor";

    private MemberModel<CompartmentModel, RootModel, IType> _model;

    public NewElementWizard() {
        setNeedsProgressMonitor(true);
    }

    /**
     * @param model - The model automatically generated by the
     * <code>CreateCommand</code>.
     */
    public void setModel(MemberModel<CompartmentModel, RootModel, IType> model) {
        _model = model;
    }

    /**
     * @return The model created by this dialog.
     */
    public MemberModel<CompartmentModel, RootModel, IType> getModel() {
        return _model;
    }

    /**
     * Subclasses should override to perform the actions of the wizard. This
     * method is run in the wizard container's context as a workspace runnable.
     * 
     * @param monitor - The progress monitor to use.
     * @throws InterruptedException
     * @throws CoreException
     */
    protected void finishPage(IProgressMonitor monitor) throws InterruptedException, CoreException {
        if (_fPage != null && _fPage.getPackageFragment().isDefaultPackage()) {
            GreenException.illegalOperation(DEFAULT_PACKAGE_ERROR);
        }
    }

    /**
     * @return True if the wizard can be run on a forked thread, false
     * otherwise.
     */
    protected abstract boolean canRunForked();

    /**
     * @see edu.buffalo.cse.green.dialogs.GreenWizard#doFinish()
     */
    public boolean doFinish() {
        final IWorkspaceRunnable op = new IWorkspaceRunnable() {
            /**
             * @see org.eclipse.core.resources.IWorkspaceRunnable#run(org.eclipse.core.runtime.IProgressMonitor)
             */
            public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
                try {
                    finishPage(monitor);
                } catch (InterruptedException e) {
                    throw new OperationCanceledException(e.getMessage());
                }
            }
        };

        try {
            getContainer().run(canRunForked(), true, new IRunnableWithProgress() {
                /**
                 * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor)
                 */
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    try {
                        op.run(monitor);
                    } catch (CoreException e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            handleFinishException(e);
            return false;
        }

        return true;
    }

    /**
     * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection)
     */
    public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
        _workbench = workbench;
        _selection = currentSelection;
    }

    /**
     * @return The selection.
     */
    public IStructuredSelection getSelection() {
        return _selection;
    }

    /**
     * @return The workbench.
     */
    public IWorkbench getWorkbench() {
        return _workbench;
    }

    /**
     * Selects and reveals the given resource in the workbench.
     * 
     * @param newResource - The resource.
     */
    protected void selectAndReveal(IResource newResource) {
        BasicNewResourceWizard.selectAndReveal(newResource, _workbench.getActiveWorkbenchWindow());
    }
}

/**
 * This is the parent class of the wizards used to create fields and methods
 * using Green's editor. It creates the controls common to both wizards and
 * provides common functionality. 
 * 
 * @author bcmartin
 */
abstract class NewMemberSignatureWizardPage extends NewElementWizardPage {
    private VisibilityComposite _visibility;

    private Button _checkboxAbstract;
    private Button _checkboxFinal;
    private Button _checkboxStatic;

    private Button _typeByte;
    private Button _typeShort;
    private Button _typeInt;
    private Button _typeLong;
    private Button _typeFloat;
    private Button _typeDouble;
    private Button _typeBoolean;
    private Button _typeChar;
    private Button _typeVoid;
    private Button _browseTypeButton;
    private Text _name;
    private boolean _isInterface;
    private Text _typeNameText;

    public NewMemberSignatureWizardPage(String name) {
        super(name);
    }

    //   /**
    //    * Sets the basic layout for the page.
    //    * 
    //    * @param parent - The container of this space.
    //    */
    //   protected void createBlankSpace(Composite parent) {
    //      Label dummyLabel = new Label(parent, SWT.SHADOW_NONE);
    //      dummyLabel.setLayoutData(new GridData());
    //   }

    /**
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        initializeDialogUnits(parent);

        Composite group = new Composite(parent, SWT.NONE);

        int columns = 4;

        GridLayout layout = new GridLayout();
        layout.numColumns = columns;
        group.setLayout(layout);

        // pick & choose the wanted UI components
        createNameControls(group, columns);
        createModifierControls(group, columns);
        populateTypeGroup(group, columns);

        setControl(group);

        Dialog.applyDialogFont(group);
        PlugIn.getWorkbenchHelp().setHelp(group, JavaUI.ID_PLUGIN + "." + "new_class_wizard_page_context");

        _typeNameText.setText("String");

        if (allowVoidType()) {
            _typeVoid.setSelection(true);
        }
    }

    /**
     * @return The user specified data type for the pending variable.
     */
    public String getTypeName() {
        if (_typeBoolean.getSelection())
            return "boolean";
        if (_typeByte.getSelection())
            return "byte";
        if (_typeChar.getSelection())
            return "char";
        if (_typeDouble.getSelection())
            return "double";
        if (_typeFloat.getSelection())
            return "float";
        if (_typeInt.getSelection())
            return "int";
        if (_typeLong.getSelection())
            return "long";
        if (_typeShort.getSelection())
            return "short";
        if (allowVoidType() && _typeVoid.getSelection())
            return "void";

        String typeName = _typeNameText.getText();
        if (typeName.startsWith("java.lang.")) {
            return typeName.substring(typeName.lastIndexOf(".") + 1);
        }

        return _typeNameText.getText();
    }

    /**
     * @return The modifiers for the pending variable.
     */
    public List<String> getModifiers() {
        List<String> flags = new ArrayList<String>();
        String visibility = _visibility.getValue().getCodeText();

        if (_checkboxAbstract != null && _checkboxAbstract.getSelection())
            flags.add("abstract");
        if (_checkboxFinal != null && _checkboxFinal.getSelection())
            flags.add("final");
        if (_checkboxStatic != null && _checkboxStatic.getSelection())
            flags.add("static");

        if (visibility != null)
            flags.add(0, visibility);

        return flags;
    }

    /**
     * @param parent - The parent of the type group.
     * @param columns - The number of columns to create.
     */
    private void populateTypeGroup(Composite parent, int columns) {
        Label typeLabel = new Label(parent, SWT.SHADOW_NONE);
        typeLabel.setText("&Return Type:");
        typeLabel.setLayoutData(new GridData());

        Composite typeSubGroup = new Composite(parent, SWT.SHADOW_NONE);
        GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        data.horizontalSpan = columns - 2;
        typeSubGroup.setLayoutData(data);
        int subGroupColumns = 5;
        typeSubGroup.setLayout(new GridLayout(subGroupColumns, true));

        // create type buttons
        if (allowVoidType()) {
            _typeVoid = new Button(typeSubGroup, SWT.RADIO);
            _typeVoid.setText("void");
            _typeVoid.setLayoutData(new GridData());
        }

        _typeByte = new Button(typeSubGroup, SWT.RADIO);
        _typeShort = new Button(typeSubGroup, SWT.RADIO);
        _typeInt = new Button(typeSubGroup, SWT.RADIO);
        _typeLong = new Button(typeSubGroup, SWT.RADIO);
        _typeFloat = new Button(typeSubGroup, SWT.RADIO);
        _typeDouble = new Button(typeSubGroup, SWT.RADIO);
        _typeBoolean = new Button(typeSubGroup, SWT.RADIO);
        _typeChar = new Button(typeSubGroup, SWT.RADIO);

        _typeByte.setText("byte");
        _typeByte.setLayoutData(new GridData());
        _typeShort.setText("short");
        _typeShort.setLayoutData(new GridData());
        _typeInt.setText("int");
        _typeInt.setLayoutData(new GridData());
        _typeLong.setText("&long");
        _typeLong.setLayoutData(new GridData());
        _typeFloat.setText("float");
        _typeFloat.setLayoutData(new GridData());
        _typeDouble.setText("double");
        _typeDouble.setLayoutData(new GridData());
        _typeBoolean.setText("boolean");
        _typeBoolean.setLayoutData(new GridData());
        _typeChar.setText("char");
        _typeChar.setLayoutData(new GridData());

        _typeNameText = new Text(parent, SWT.HORIZONTAL | SWT.LEFT | SWT.BORDER | SWT.SINGLE);
        data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        data.horizontalSpan = columns - 1;
        _typeNameText.setLayoutData(data);
        _typeNameText.setText("Object");
        _typeNameText.setEnabled(false);

        _browseTypeButton = new Button(parent, SWT.PUSH | SWT.CENTER);
        _browseTypeButton.setText("&Browse ...");
        _browseTypeButton.setLayoutData(new GridData());
        _browseTypeButton.addSelectionListener(new SelectionListener() {
            /**
             * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
             */
            public void widgetSelected(SelectionEvent e) {
                List<IType> types = new ChooseTypeDialog(false).open();

                if (!types.isEmpty()) {
                    String selectedName = types.get(0).getFullyQualifiedName();
                    _typeNameText.setText(selectedName);
                    _typeBoolean.setSelection(false);
                    _typeByte.setSelection(false);
                    _typeChar.setSelection(false);
                    _typeDouble.setSelection(false);
                    _typeFloat.setSelection(false);
                    _typeInt.setSelection(false);
                    _typeLong.setSelection(false);
                    _typeShort.setSelection(false);
                    if (allowVoidType())
                        _typeVoid.setSelection(false);
                }
            }

            /**
             * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
             */
            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
    }

    /**
     * Creates the controls for the modifier section of the page.
     * 
     * @param parent - The parent of the modifier controls group.
     * @param columns - The number of columns to create.
     */
    private void createModifierControls(Composite parent, int columns) {
        final NewElementWizardSettings settings = getSettings();
        Label modifiersLabel = new Label(parent, SWT.SHADOW_NONE | SWT.LEFT);
        modifiersLabel.setText("&Modifiers:");
        modifiersLabel.setLayoutData(new GridData());

        _visibility = new VisibilityComposite(parent, 0, false);
        _visibility.addListener(new IVisibilityChangedListener() {
            public void visibilityChanged(MemberVisibility value) {
                if (value.equals(MemberVisibility.PRIVATE)) {
                    if (settings.isAbstractAvailable()) {
                        _checkboxAbstract.setSelection(false);
                    }
                }
            }
        });

        GridData data = new GridData();
        data.horizontalSpan = 3;
        _visibility.setLayoutData(data);

        if (settings.isAbstractAvailable()) {
            _checkboxAbstract = new Button(_visibility, SWT.CHECK);
            _checkboxAbstract.setText("abstract");
            _checkboxAbstract.setEnabled(settings.isAbstractEnabled());
            _checkboxAbstract.setSelection(settings.isAbstractSelected());

            _checkboxAbstract.addSelectionListener(new SelectionListener() {
                /**
                 * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent)
                 */
                public void widgetSelected(SelectionEvent e) {
                    if (settings.isFinalAvailable()) {
                        _checkboxFinal.setSelection(false);

                        if (getVisibilityContainer().getValue().equals(MemberVisibility.PRIVATE)) {
                            getVisibilityContainer().setPrivateSelected(false);
                            getVisibilityContainer().setProtectedSelected(true);
                        }
                    }
                }

                /**
                 * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent)
                 */
                public void widgetDefaultSelected(SelectionEvent e) {
                }
            });
        }

        if (settings.isFinalAvailable()) {
            _checkboxFinal = new Button(_visibility, SWT.CHECK);
            _checkboxFinal.setText("final");
            _checkboxFinal.setEnabled(settings.isFinalEnabled());
            _checkboxFinal.setSelection(settings.isFinalSelected());

            _checkboxFinal.addSelectionListener(new SelectionListener() {
                public void widgetSelected(SelectionEvent e) {
                    if (settings.isAbstractAvailable()) {
                        _checkboxAbstract.setSelection(false);
                    }
                }

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

        if (settings.isStaticAvailable()) {
            _checkboxStatic = new Button(_visibility, SWT.CHECK);
            _checkboxStatic.setText("static");
            _checkboxStatic.setEnabled(settings.isStaticEnabled());
            _checkboxStatic.setSelection(settings.isStaticSelected());
        }
    }

    /**
     * @return The <code>Composite</code> that holds the visibility buttons.
     */
    protected VisibilityComposite getVisibilityContainer() {
        return _visibility;
    }

    /**
     * Creates the controls for the name section of the page.
     * 
     * @param composite - The parent of the modifier controls group.
     * @param columns - The number of columns to create.
     */
    private void createNameControls(Composite composite, int columns) {
        Label nameLabel = new Label(composite, SWT.HORIZONTAL | SWT.LEFT | SWT.SHADOW_NONE);
        nameLabel.setText("&Name");
        GridData data = new GridData();
        nameLabel.setLayoutData(data);

        _name = new Text(composite, SWT.HORIZONTAL | SWT.LEFT | SWT.BORDER | SWT.SINGLE);
        data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        data.horizontalSpan = columns - 1;
        _name.setLayoutData(data);

        if (isField())
            _name.setText(VariableAffix.getAffixString(FieldPrefix));
        else
            _name.setText("");

        _name.setSelection(0, _name.getText().length());

        final WizardPage page = this;

        _name.addKeyListener(new KeyListener() {
            /**
             * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
             */
            public void keyPressed(KeyEvent e) {
            }

            /**
             * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
             */
            public void keyReleased(KeyEvent e) {
                Pattern p = Pattern.compile("[_abcdefghijklmnopqrstuvwxyz]\\w*");
                Matcher m = p.matcher(_name.getText());

                if (!m.matches()) {
                    page.setErrorMessage("Invalid name");
                } else {
                    page.setErrorMessage(null);
                }
            }
        });

        page.setErrorMessage("Invalid name");
    }

    /**
     * @see org.eclipse.jface.wizard.IWizardPage#getName()
     */
    public String getName() {
        return _name.getText();
    }

    /**
     * Sets whether or not we are creating the element in an interface.
     * 
     * @param isInterface - The value to use.
     */
    protected void setInterface(boolean isInterface) {
        _isInterface = isInterface;
    }

    /**
     * @return Provides settings used to fill out the dialog.
     */
    protected abstract NewElementWizardSettings getSettings();

    /**
     * @return true if void is a valid data type, false otherwise.
     */
    protected abstract boolean allowVoidType();

    protected abstract boolean isField();

    /**
     * @return true if this element wizard is being used to add an element to an
     * interface, false otherwise.
     */
    protected boolean isInterface() {
        return _isInterface;
    }
}