ext.org.eclipse.jdt.internal.ui.refactoring.PullUpMemberPage.java Source code

Java tutorial

Introduction

Here is the source code for ext.org.eclipse.jdt.internal.ui.refactoring.PullUpMemberPage.java

Source

/*******************************************************************************
 * Copyright (c) 2006, 2011 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 ext.org.eclipse.jdt.internal.ui.refactoring;

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

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.CheckStateChangedEvent;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ComboBoxCellEditor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ICheckStateListener;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizardPage;

import org.eclipse.ui.PlatformUI;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.ui.refactoring.UserInputWizardPage;

import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.JavaElementLabelProvider;
import org.eclipse.jdt.ui.JavaElementLabels;

import patch.org.eclipse.jdt.internal.ui.JavaPlugin;

import ext.org.eclipse.jdt.internal.corext.refactoring.structure.IMemberActionInfo;
import ext.org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor;
import ext.org.eclipse.jdt.internal.corext.util.JdtFlags;
import ext.org.eclipse.jdt.internal.corext.util.Messages;
import ext.org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import ext.org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import ext.org.eclipse.jdt.internal.ui.util.SWTUtil;
import ext.org.eclipse.jdt.internal.ui.util.TableLayoutComposite;

/**
 * Wizard page for pull up refactoring wizards which allows to specify the
 * actions on the members to pull up.
 *
 * @since 3.2
 */
public class PullUpMemberPage extends UserInputWizardPage {

    private class MemberActionCellModifier implements ICellModifier {

        public boolean canModify(final Object element, final String property) {
            if (!ACTION_PROPERTY.equals(property))
                return false;
            return ((MemberActionInfo) element).isEditable();
        }

        public Object getValue(final Object element, final String property) {
            if (!ACTION_PROPERTY.equals(property))
                return null;
            final MemberActionInfo info = (MemberActionInfo) element;
            return new Integer(info.getAction());
        }

        public void modify(final Object element, final String property, final Object value) {
            if (!ACTION_PROPERTY.equals(property))
                return;
            final int action = ((Integer) value).intValue();
            MemberActionInfo info;
            if (element instanceof Item) {
                info = (MemberActionInfo) ((Item) element).getData();
            } else
                info = (MemberActionInfo) element;
            if (!canModify(info, property))
                return;
            Assert.isTrue(info.isMethodInfo());
            info.setAction(action);
            updateWizardPage(null, true);
        }
    }

    private class MemberActionInfo implements IMemberActionInfo {

        private static final int NO_ACTION = 2;

        private int fAction;

        private final IMember fMember;

        public MemberActionInfo(final IMember member, final int action) {
            Assert.isTrue((member instanceof IMethod) || (member instanceof IField) || (member instanceof IType));
            assertAction(member, action);
            fMember = member;
            fAction = action;
        }

        private void assertAction(final IMember member, final int action) {
            if (member instanceof IMethod) {
                try {
                    Assert.isTrue(action != DECLARE_ABSTRACT_ACTION || !JdtFlags.isStatic(member));
                } catch (JavaModelException e) {
                    JavaPlugin.log(e);
                }
                Assert.isTrue(action == NO_ACTION || action == DECLARE_ABSTRACT_ACTION || action == PULL_UP_ACTION);
            } else {
                Assert.isTrue(action == NO_ACTION || action == PULL_UP_ACTION);
            }
        }

        public int getAction() {
            return fAction;
        }

        public String getActionLabel() {
            switch (fAction) {
            case PULL_UP_ACTION:
                return getPullUpActionLabel();
            case DECLARE_ABSTRACT_ACTION:
                return getDeclareAbstractActionLabel();
            case NO_ACTION:
                return ""; //$NON-NLS-1$
            default:
                Assert.isTrue(false);
                return null;
            }
        }

        public String[] getAllowedLabels() {
            if (isFieldInfo())
                return new String[] { "" }; //$NON-NLS-1$
            else if (isMethodInfo())
                return METHOD_LABELS;
            else if (isTypeInfo())
                return TYPE_LABELS;
            else {
                Assert.isTrue(false);
                return null;
            }
        }

        public IMember getMember() {
            return fMember;
        }

        public boolean isActive() {
            return getAction() != NO_ACTION;
        }

        public boolean isEditable() {
            if (fAction == NO_ACTION)
                return false;
            if (!isMethodInfo())
                return false;
            final IMethod method = (IMethod) fMember;
            try {
                return !JdtFlags.isStatic(method);
            } catch (JavaModelException e) {
                JavaPlugin.log(e);
                return false;
            }
        }

        public boolean isFieldInfo() {
            return getMember() instanceof IField;
        }

        public boolean isMethodInfo() {
            return getMember() instanceof IMethod;
        }

        public boolean isTypeInfo() {
            return getMember() instanceof IType;
        }

        public void setAction(final int action) {
            assertAction(fMember, action);
            fAction = action;
        }
    }

    private static class MemberActionInfoLabelProvider extends LabelProvider implements ITableLabelProvider {

        private final ILabelProvider fLabelProvider = new JavaElementLabelProvider(
                JavaElementLabelProvider.SHOW_DEFAULT | JavaElementLabelProvider.SHOW_SMALL_ICONS);

        @Override
        public void dispose() {
            super.dispose();
            fLabelProvider.dispose();
        }

        public Image getColumnImage(final Object element, final int columnIndex) {
            final MemberActionInfo info = (MemberActionInfo) element;
            switch (columnIndex) {
            case MEMBER_COLUMN:
                return fLabelProvider.getImage(info.getMember());
            case ACTION_COLUMN:
                return null;
            default:
                Assert.isTrue(false);
                return null;
            }
        }

        public String getColumnText(final Object element, final int columnIndex) {
            final MemberActionInfo info = (MemberActionInfo) element;
            switch (columnIndex) {
            case MEMBER_COLUMN:
                return fLabelProvider.getText(info.getMember());
            case ACTION_COLUMN:
                return info.getActionLabel();
            default:
                Assert.isTrue(false);
                return null;
            }
        }
    }

    private static final int ACTION_COLUMN = 1;

    private static final String ACTION_PROPERTY = "action"; //$NON-NLS-1$

    protected static final int DECLARE_ABSTRACT_ACTION = 1;

    private static final int MEMBER_COLUMN = 0;

    private static final String MEMBER_PROPERTY = "member"; //$NON-NLS-1$

    protected static final int PULL_UP_ACTION = 0;

    private static final String SETTING_INSTANCEOF = "InstanceOf"; //$NON-NLS-1$

    private static final String SETTING_REPLACE = "Replace"; //$NON-NLS-1$

    private static int getEditableCount(final MemberActionInfo[] infos) {
        int result = 0;
        for (int i = 0; i < infos.length; i++) {
            final MemberActionInfo info = infos[i];
            if (info.isEditable())
                result++;
        }
        return result;
    }

    private static void putToStringMapping(final Map<String, Integer> result, final String[] actionLabels,
            final int actionIndex) {
        result.put(actionLabels[actionIndex], new Integer(actionIndex));
    }

    private static void setActionForInfos(final MemberActionInfo[] infos, final int action) {
        for (int i = 0; i < infos.length; i++) {
            infos[i].setAction(action);
        }
    }

    private Button fAddButton;

    protected IType[] fCandidateTypes = {};

    private Button fCreateStubsButton;

    private Button fDeselectAllButton;

    private Button fEditButton;

    private Button fInstanceofButton;

    private Label fLabel;

    private Button fReplaceButton;

    private Button fSelectAllButton;

    private Label fStatusLine;

    protected final PullUpMethodPage fSuccessorPage;

    private Combo fSuperTypesCombo;

    private CheckboxTableViewer fTableViewer;

    protected final String[] METHOD_LABELS;

    protected final String[] TYPE_LABELS;

    private final PullUpRefactoringProcessor fProcessor;

    public PullUpMemberPage(final String name, final PullUpMethodPage page, PullUpRefactoringProcessor processor) {
        super(name);
        fSuccessorPage = page;
        fProcessor = processor;
        setDescription(RefactoringMessages.PullUpInputPage1_page_message);
        METHOD_LABELS = new String[2];
        METHOD_LABELS[PULL_UP_ACTION] = RefactoringMessages.PullUpInputPage1_pull_up;
        METHOD_LABELS[DECLARE_ABSTRACT_ACTION] = RefactoringMessages.PullUpInputPage1_declare_abstract;

        TYPE_LABELS = new String[1];
        TYPE_LABELS[PULL_UP_ACTION] = RefactoringMessages.PullUpInputPage1_pull_up;
    }

    public PullUpRefactoringProcessor getPullUpRefactoringProcessor() {
        return fProcessor;
    }

    private boolean areAllMembersMarkedAsPullUp() {
        return getMembersForAction(PULL_UP_ACTION).length == getTableInput().length;
    }

    protected boolean areAllMembersMarkedAsWithNoAction() {
        return getMembersForAction(MemberActionInfo.NO_ACTION).length == getTableInput().length;
    }

    private MemberActionInfo[] asMemberActionInfos() {
        final List<IMember> toPullUp = Arrays.asList(fProcessor.getMembersToMove());
        final IMember[] members = fProcessor.getPullableMembersOfDeclaringType();
        final MemberActionInfo[] result = new MemberActionInfo[members.length];
        for (int i = 0; i < members.length; i++) {
            final IMember member = members[i];
            if (toPullUp.contains(member))
                result[i] = new MemberActionInfo(member, PULL_UP_ACTION);
            else
                result[i] = new MemberActionInfo(member, MemberActionInfo.NO_ACTION);
        }
        return result;
    }

    @Override
    public boolean canFlipToNextPage() {
        return isPageComplete();
    }

    private void checkAdditionalRequired() {
        try {
            initializeRefactoring();

            class GetRequiredMembersRunnable implements IRunnableWithProgress {
                public IMember[] result;

                public void run(final IProgressMonitor pm) throws InvocationTargetException {
                    try {
                        this.result = fProcessor.getAdditionalRequiredMembersToPullUp(pm);
                    } catch (JavaModelException e) {
                        throw new InvocationTargetException(e);
                    } finally {
                        pm.done();
                    }
                }
            }
            GetRequiredMembersRunnable runnable = new GetRequiredMembersRunnable();
            getContainer().run(true, false, runnable);
            checkPullUp(runnable.result, true);

        } catch (InvocationTargetException e) {
            ExceptionHandler.handle(e, getShell(), RefactoringMessages.PullUpInputPage_pull_Up,
                    RefactoringMessages.PullUpInputPage_exception);
        } catch (InterruptedException e) {
            Assert.isTrue(false);
        }
    }

    protected void checkPageCompletionStatus(final boolean displayErrors) {
        if (areAllMembersMarkedAsWithNoAction()) {
            if (displayErrors)
                setErrorMessage(getNoMembersMessage());
            setPageComplete(false);
        } else {
            setErrorMessage(null);
            setPageComplete(true);
        }
        fSuccessorPage.fireSettingsChanged();
    }

    private void checkPullUp(final IMember[] elements, final boolean displayErrors) {
        setActionForMembers(elements, PULL_UP_ACTION);
        updateWizardPage(null, displayErrors);
    }

    private void createButtonComposite(final Composite parent) {
        final Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
        final GridLayout gl = new GridLayout();
        gl.marginHeight = 0;
        gl.marginWidth = 0;
        composite.setLayout(gl);

        fSelectAllButton = new Button(composite, SWT.PUSH);
        fSelectAllButton.setText(RefactoringMessages.PullUpWizard_select_all_label);
        fSelectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        fSelectAllButton.setEnabled(true);
        SWTUtil.setButtonDimensionHint(fSelectAllButton);
        fSelectAllButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent event) {
                final IMember[] members = getMembers();
                setActionForMembers(members, PULL_UP_ACTION);
                updateWizardPage(null, true);
            }
        });

        fDeselectAllButton = new Button(composite, SWT.PUSH);
        fDeselectAllButton.setText(RefactoringMessages.PullUpWizard_deselect_all_label);
        fDeselectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        fDeselectAllButton.setEnabled(false);
        SWTUtil.setButtonDimensionHint(fDeselectAllButton);
        fDeselectAllButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent event) {
                final IMember[] members = getMembers();
                setActionForMembers(members, MemberActionInfo.NO_ACTION);
                updateWizardPage(null, true);
            }
        });

        fEditButton = new Button(composite, SWT.PUSH);
        fEditButton.setText(RefactoringMessages.PullUpInputPage1_Edit);

        final GridData data = new GridData(GridData.FILL_HORIZONTAL);
        data.verticalIndent = new PixelConverter(parent)
                .convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
        fEditButton.setLayoutData(data);
        fEditButton.setEnabled(false);
        SWTUtil.setButtonDimensionHint(fEditButton);
        fEditButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent event) {
                editSelectedMembers();
            }
        });

        fAddButton = new Button(composite, SWT.PUSH);
        fAddButton.setText(RefactoringMessages.PullUpInputPage1_Add_Required);
        fAddButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        SWTUtil.setButtonDimensionHint(fAddButton);
        fAddButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent event) {
                checkAdditionalRequired();
            }
        });
    }

    public void createControl(final Composite parent) {
        final Composite composite = new Composite(parent, SWT.NONE);
        final GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        composite.setLayout(layout);

        createSuperTypeControl(composite);
        createSpacer(composite);
        createSuperTypeCheckbox(composite);
        createInstanceOfCheckbox(composite, layout.marginWidth);
        createStubCheckbox(composite);
        createSpacer(composite);
        createMemberTableLabel(composite);
        createMemberTableComposite(composite);
        createStatusLine(composite);

        setControl(composite);
        Dialog.applyDialogFont(composite);
        initializeEnablement();
        initializeCheckboxes();
        PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaHelpContextIds.PULL_UP_WIZARD_PAGE);
    }

    protected void createInstanceOfCheckbox(final Composite result, final int margin) {
        fInstanceofButton = new Button(result, SWT.CHECK);
        fInstanceofButton.setSelection(false);
        final GridData gd = new GridData();
        gd.horizontalIndent = (margin + fInstanceofButton.computeSize(SWT.DEFAULT, SWT.DEFAULT).x);
        gd.horizontalSpan = 2;
        fInstanceofButton.setLayoutData(gd);
        fInstanceofButton.setText(getInstanceofButtonLabel());
        fProcessor.setInstanceOf(fInstanceofButton.getSelection());
        fInstanceofButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent e) {
                fProcessor.setInstanceOf(fInstanceofButton.getSelection());
            }
        });
        fReplaceButton.addSelectionListener(new SelectionAdapter() {

            @Override
            public void widgetSelected(final SelectionEvent e) {
                fInstanceofButton.setEnabled(fReplaceButton.getSelection());
            }
        });
    }

    private void createMemberTable(final Composite parent) {
        final TableLayoutComposite layouter = new TableLayoutComposite(parent, SWT.NONE);
        layouter.addColumnData(new ColumnWeightData(60, true));
        layouter.addColumnData(new ColumnWeightData(40, true));

        final Table table = new Table(layouter,
                SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION | SWT.CHECK);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        final GridData gd = new GridData(GridData.FILL_BOTH);
        gd.heightHint = SWTUtil.getTableHeightHint(table, getTableRowCount());
        gd.widthHint = convertWidthInCharsToPixels(30);
        layouter.setLayoutData(gd);

        final TableLayout tableLayout = new TableLayout();
        table.setLayout(tableLayout);

        final TableColumn column0 = new TableColumn(table, SWT.NONE);
        column0.setText(RefactoringMessages.PullUpInputPage1_Member);

        final TableColumn column1 = new TableColumn(table, SWT.NONE);
        column1.setText(RefactoringMessages.PullUpInputPage1_Action);

        fTableViewer = new PullPushCheckboxTableViewer(table);
        fTableViewer.setUseHashlookup(true);
        fTableViewer.setContentProvider(new ArrayContentProvider());
        fTableViewer.setLabelProvider(new MemberActionInfoLabelProvider());
        fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(final SelectionChangedEvent event) {
                updateButtonEnablement(event.getSelection());
            }
        });
        fTableViewer.addCheckStateListener(new ICheckStateListener() {

            public void checkStateChanged(final CheckStateChangedEvent event) {
                final boolean checked = event.getChecked();
                final MemberActionInfo info = (MemberActionInfo) event.getElement();
                if (checked)
                    info.setAction(PULL_UP_ACTION);
                else
                    info.setAction(MemberActionInfo.NO_ACTION);
                updateWizardPage(null, true);
            }
        });
        fTableViewer.addDoubleClickListener(new IDoubleClickListener() {

            public void doubleClick(final DoubleClickEvent event) {
                editSelectedMembers();
            }
        });

        setTableInput();
        checkPullUp(fProcessor.getMembersToMove(), false);
        setupCellEditors(table);
    }

    protected void createMemberTableComposite(final Composite parent) {
        final Composite composite = new Composite(parent, SWT.NONE);
        final GridData data = new GridData(GridData.FILL_BOTH);
        data.horizontalSpan = 2;
        composite.setLayoutData(data);
        final GridLayout layout = new GridLayout();
        layout.numColumns = 2;
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        composite.setLayout(layout);

        createMemberTable(composite);
        createButtonComposite(composite);
    }

    protected void createMemberTableLabel(final Composite parent) {
        fLabel = new Label(parent, SWT.NONE);
        fLabel.setText(RefactoringMessages.PullUpInputPage1_Specify_actions);
        final GridData data = new GridData();
        data.horizontalSpan = 2;
        fLabel.setLayoutData(data);
    }

    protected void createSpacer(final Composite parent) {
        final Label label = new Label(parent, SWT.NONE);
        final GridData data = new GridData();
        data.horizontalSpan = 2;
        data.heightHint = convertHeightInCharsToPixels(1) / 2;
        label.setLayoutData(data);
    }

    protected void createStatusLine(final Composite composite) {
        fStatusLine = new Label(composite, SWT.NONE);
        final GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false);
        data.horizontalSpan = 2;
        updateStatusLine();
        fStatusLine.setLayoutData(data);
    }

    // String -> Integer
    private Map<String, Integer> createStringMappingForSelectedMembers() {
        final Map<String, Integer> result = new HashMap<String, Integer>();
        putToStringMapping(result, METHOD_LABELS, PULL_UP_ACTION);
        putToStringMapping(result, METHOD_LABELS, DECLARE_ABSTRACT_ACTION);
        return result;
    }

    protected void createStubCheckbox(final Composite parent) {
        fCreateStubsButton = new Button(parent, SWT.CHECK);
        fCreateStubsButton.setText(getCreateStubsButtonLabel());
        final GridData data = new GridData();
        data.horizontalSpan = 2;
        fCreateStubsButton.setLayoutData(data);
        fCreateStubsButton.setEnabled(false);
        fCreateStubsButton.setSelection(fProcessor.getCreateMethodStubs());
    }

    protected void createSuperTypeCheckbox(final Composite parent) {
        fReplaceButton = new Button(parent, SWT.CHECK);
        fReplaceButton.setText(getReplaceButtonLabel());
        final GridData data = new GridData();
        data.horizontalSpan = 2;
        fReplaceButton.setLayoutData(data);
        fReplaceButton.setEnabled(true);
        fReplaceButton.setSelection(fProcessor.isReplace());
    }

    private void createSuperTypeCombo(Composite parent) {
        final Label label = new Label(parent, SWT.NONE);
        label.setText(RefactoringMessages.PullUpInputPage1_Select_destination);
        label.setLayoutData(new GridData());

        fSuperTypesCombo = new Combo(parent, SWT.READ_ONLY);
        SWTUtil.setDefaultVisibleItemCount(fSuperTypesCombo);
        if (fCandidateTypes.length > 0) {
            for (int i = 0; i < fCandidateTypes.length; i++) {
                final String comboLabel = fCandidateTypes[i].getFullyQualifiedName('.');
                fSuperTypesCombo.add(comboLabel);
            }
            fSuperTypesCombo.select(fCandidateTypes.length - 1);
            fSuperTypesCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        }
    }

    protected void createSuperTypeControl(final Composite parent) {
        try {
            PlatformUI.getWorkbench().getActiveWorkbenchWindow().run(true, false, new IRunnableWithProgress() {
                public void run(final IProgressMonitor monitor) throws InvocationTargetException {
                    try {
                        fCandidateTypes = fProcessor.getCandidateTypes(new RefactoringStatus(), monitor);
                    } catch (JavaModelException exception) {
                        throw new InvocationTargetException(exception);
                    } finally {
                        monitor.done();
                    }
                }
            });
            createSuperTypeCombo(parent);
        } catch (InvocationTargetException exception) {
            ExceptionHandler.handle(exception, getShell(), RefactoringMessages.PullUpInputPage_pull_Up,
                    RefactoringMessages.PullUpInputPage_exception);
        } catch (InterruptedException exception) {
            Assert.isTrue(false);
        }
    }

    @Override
    public void dispose() {
        fInstanceofButton = null;
        fReplaceButton = null;
        fTableViewer = null;
        super.dispose();
    }

    private void editSelectedMembers() {
        if (!fEditButton.isEnabled())
            return;

        final ISelection preserved = fTableViewer.getSelection();
        try {
            MemberActionInfo[] selectedMembers = getSelectedMembers();
            final String shellTitle = RefactoringMessages.PullUpInputPage1_Edit_members;
            final String labelText = selectedMembers.length == 1
                    ? Messages.format(RefactoringMessages.PullUpInputPage1_Mark_selected_members_singular,
                            JavaElementLabels.getElementLabel(selectedMembers[0].getMember(),
                                    JavaElementLabels.M_PARAMETER_TYPES))
                    : Messages.format(RefactoringMessages.PullUpInputPage1_Mark_selected_members_plural,
                            String.valueOf(selectedMembers.length));
            final Map<String, Integer> stringMapping = createStringMappingForSelectedMembers();
            final String[] keys = stringMapping.keySet().toArray(new String[stringMapping.keySet().size()]);
            Arrays.sort(keys);
            final int initialSelectionIndex = getInitialSelectionIndexForEditDialog(stringMapping, keys);
            final ComboSelectionDialog dialog = new ComboSelectionDialog(getShell(), shellTitle, labelText, keys,
                    initialSelectionIndex);
            dialog.setBlockOnOpen(true);
            if (dialog.open() == Window.CANCEL)
                return;
            final int action = stringMapping.get(dialog.getSelectedString()).intValue();
            setActionForInfos(selectedMembers, action);
        } finally {
            updateWizardPage(preserved, true);
        }
    }

    private boolean enableEditButton(final IStructuredSelection ss) {
        if (ss.isEmpty() || ss.size() == 0)
            return false;
        return ss.size() == getEditableCount(getSelectedMembers());
    }

    private MemberActionInfo[] getActiveInfos() {
        final MemberActionInfo[] infos = getTableInput();
        final List<MemberActionInfo> result = new ArrayList<MemberActionInfo>(infos.length);
        for (int i = 0; i < infos.length; i++) {
            final MemberActionInfo info = infos[i];
            if (info.isActive())
                result.add(info);
        }
        return result.toArray(new MemberActionInfo[result.size()]);
    }

    private int getCommonActionCodeForSelectedInfos() {
        final MemberActionInfo[] infos = getSelectedMembers();
        if (infos.length == 0)
            return -1;

        final int code = infos[0].getAction();
        for (int i = 0; i < infos.length; i++) {
            if (code != infos[i].getAction())
                return -1;
        }
        return code;
    }

    protected String getCreateStubsButtonLabel() {
        return RefactoringMessages.PullUpInputPage1_Create_stubs;
    }

    protected String getDeclareAbstractActionLabel() {
        return RefactoringMessages.PullUpInputPage1_declare_abstract;
    }

    public IType getDestinationType() {
        final int index = fSuperTypesCombo.getSelectionIndex();
        if (index >= 0)
            return fCandidateTypes[index];
        return null;
    }

    private int getInitialSelectionIndexForEditDialog(final Map<String, Integer> stringMapping,
            final String[] keys) {
        final int commonActionCode = getCommonActionCodeForSelectedInfos();
        if (commonActionCode == -1)
            return 0;
        for (final Iterator<String> iter = stringMapping.keySet().iterator(); iter.hasNext();) {
            final String key = iter.next();
            final int action = stringMapping.get(key).intValue();
            if (commonActionCode == action) {
                for (int i = 0; i < keys.length; i++) {
                    if (key.equals(keys[i]))
                        return i;
                }
                Assert.isTrue(false);
            }
        }
        return 0;
    }

    protected String getInstanceofButtonLabel() {
        return RefactoringMessages.PullUpInputPage1_label_use_in_instanceof;
    }

    private IMember[] getMembers() {
        final MemberActionInfo[] infos = getTableInput();
        final List<IMember> result = new ArrayList<IMember>(infos.length);
        for (int index = 0; index < infos.length; index++) {
            result.add(infos[index].getMember());
        }
        return result.toArray(new IMember[result.size()]);
    }

    private IMember[] getMembersForAction(final int action) {
        List<IMember> result = new ArrayList<IMember>();
        getMembersForAction(action, false, result);
        return result.toArray(new IMember[result.size()]);
    }

    private IMethod[] getMethodsForAction(final int action) {
        List<IMember> result = new ArrayList<IMember>();
        getMembersForAction(action, true, result);
        return result.toArray(new IMethod[result.size()]);
    }

    private void getMembersForAction(int action, boolean onlyMethods, List<IMember> result) {
        boolean isDestinationInterface = isDestinationInterface();
        final MemberActionInfo[] infos = getTableInput();
        for (int index = 0; index < infos.length; index++) {
            MemberActionInfo info = infos[index];
            int infoAction = info.getAction();
            boolean isMethodInfo = info.isMethodInfo();
            if (!isMethodInfo && onlyMethods)
                continue;
            if (isMethodInfo && isDestinationInterface) {
                if (action == PULL_UP_ACTION)
                    continue; // skip methods pulled up to interface
                if (action == DECLARE_ABSTRACT_ACTION && infoAction == PULL_UP_ACTION)
                    infoAction = DECLARE_ABSTRACT_ACTION; // method pulled to interface must be declared abstract
            }
            if (infoAction == action)
                result.add(info.getMember());
        }
    }

    private boolean isDestinationInterface() {
        IType destination = getDestinationType();
        try {
            if (destination != null && destination.isInterface()) {
                return true;
            }
        } catch (JavaModelException exception) {
            JavaPlugin.log(exception);
        }
        return false;
    }

    @Override
    public IWizardPage getNextPage() {
        initializeRefactoring();
        storeDialogSettings();
        if (getMethodsForAction(PULL_UP_ACTION).length == 0)
            return computeSuccessorPage();
        if (isDestinationInterface())
            return computeSuccessorPage();
        return super.getNextPage();
    }

    protected String getNoMembersMessage() {
        return RefactoringMessages.PullUpInputPage1_Select_members_to_pull_up;
    }

    protected String getPullUpActionLabel() {
        return RefactoringMessages.PullUpInputPage1_pull_up;
    }

    protected String getReplaceButtonLabel() {
        return RefactoringMessages.PullUpInputPage1_label_use_destination;
    }

    private MemberActionInfo[] getSelectedMembers() {
        Assert.isTrue(fTableViewer.getSelection() instanceof IStructuredSelection);
        final IStructuredSelection structured = (IStructuredSelection) fTableViewer.getSelection();
        final List<?> result = structured.toList();
        return result.toArray(new MemberActionInfo[result.size()]);
    }

    private MemberActionInfo[] getTableInput() {
        return (MemberActionInfo[]) fTableViewer.getInput();
    }

    protected int getTableRowCount() {
        return 10;
    }

    private void initializeCheckBox(final Button checkbox, final String property, final boolean def) {
        final String s = JavaPlugin.getDefault().getDialogSettings().get(property);
        if (s != null)
            checkbox.setSelection(new Boolean(s).booleanValue());
        else
            checkbox.setSelection(def);
    }

    protected void initializeCheckboxes() {
        initializeCheckBox(fReplaceButton, SETTING_REPLACE, true);
        initializeCheckBox(fInstanceofButton, SETTING_INSTANCEOF, false);
    }

    protected void initializeEnablement() {
        MemberActionInfo[] infos = asMemberActionInfos();
        final boolean enabled = infos.length > 0;
        fTableViewer.getTable().setEnabled(enabled);
        fStatusLine.setEnabled(enabled);
        fAddButton.setEnabled(enabled);
        fLabel.setEnabled(enabled);
    }

    private void initializeRefactoring() {
        fProcessor.setMembersToMove(getMembersForAction(PULL_UP_ACTION));
        fProcessor.setAbstractMethods(getMethodsForAction(DECLARE_ABSTRACT_ACTION));
        final IType destination = getDestinationType();
        if (destination != null)
            fProcessor.setDestinationType(destination);
        fProcessor.setCreateMethodStubs(fCreateStubsButton.getSelection());
        fProcessor.setReplace(fReplaceButton.getSelection());
        fProcessor.setInstanceOf(fInstanceofButton.getSelection());
        fProcessor.setDeletedMethods(getMethodsForAction(PULL_UP_ACTION));
    }

    @Override
    protected boolean performFinish() {
        initializeRefactoring();
        storeDialogSettings();
        return super.performFinish();
    }

    private void setActionForMembers(final IMember[] members, final int action) {
        final MemberActionInfo[] infos = getTableInput();
        for (int i = 0; i < members.length; i++) {
            for (int j = 0; j < infos.length; j++) {
                if (infos[j].getMember().equals(members[i]))
                    infos[j].setAction(action);
            }
        }
    }

    private void setTableInput() {
        fTableViewer.setInput(asMemberActionInfos());
    }

    private void setupCellEditors(final Table table) {
        final ComboBoxCellEditor editor = new ComboBoxCellEditor();
        editor.setStyle(SWT.READ_ONLY);
        fTableViewer.setCellEditors(new CellEditor[] { null, editor });
        fTableViewer.addSelectionChangedListener(new ISelectionChangedListener() {

            public void selectionChanged(final SelectionChangedEvent event) {
                if (editor.getControl() == null & !table.isDisposed())
                    editor.create(table);
                final ISelection sel = event.getSelection();
                if (!(sel instanceof IStructuredSelection))
                    return;
                final IStructuredSelection structured = (IStructuredSelection) sel;
                if (structured.size() != 1)
                    return;
                final MemberActionInfo info = (MemberActionInfo) structured.getFirstElement();
                editor.setItems(info.getAllowedLabels());
                editor.setValue(new Integer(info.getAction()));
            }
        });

        final ICellModifier cellModifier = new MemberActionCellModifier();
        fTableViewer.setCellModifier(cellModifier);
        fTableViewer.setColumnProperties(new String[] { MEMBER_PROPERTY, ACTION_PROPERTY });
    }

    @Override
    public void setVisible(final boolean visible) {
        super.setVisible(visible);
        if (visible) {
            try {
                fProcessor.resetEnvironment();
            } finally {
                fTableViewer.setSelection(new StructuredSelection(getActiveInfos()), true);
                fTableViewer.getControl().setFocus();
            }
        }
    }

    private void storeDialogSettings() {
        final IDialogSettings settings = JavaPlugin.getDefault().getDialogSettings();
        settings.put(SETTING_REPLACE, fReplaceButton.getSelection());
        settings.put(SETTING_INSTANCEOF, fInstanceofButton.getSelection());
    }

    private void updateButtonEnablement(final ISelection selection) {
        if (fEditButton != null)
            fEditButton.setEnabled(enableEditButton((IStructuredSelection) selection));
        fCreateStubsButton.setEnabled(getMethodsForAction(DECLARE_ABSTRACT_ACTION).length != 0);
        fInstanceofButton.setEnabled(fReplaceButton.getSelection());
        if (fSelectAllButton != null)
            fSelectAllButton.setEnabled(!areAllMembersMarkedAsPullUp());
        if (fDeselectAllButton != null)
            fDeselectAllButton.setEnabled(!areAllMembersMarkedAsWithNoAction());
    }

    private void updateStatusLine() {
        if (fStatusLine == null)
            return;
        Object[] selectedMembers = fTableViewer.getCheckedElements();
        final int selected = selectedMembers.length;
        final String msg = selected == 1
                ? Messages.format(RefactoringMessages.PullUpInputPage1_status_line_singular,
                        JavaElementLabels.getElementLabel(((MemberActionInfo) selectedMembers[0]).getMember(),
                                JavaElementLabels.M_PARAMETER_TYPES))
                : Messages.format(RefactoringMessages.PullUpInputPage1_status_line_plural,
                        String.valueOf(selected));
        fStatusLine.setText(msg);
    }

    private void updateWizardPage(final ISelection selection, final boolean displayErrors) {
        fTableViewer.refresh();
        if (selection != null) {
            fTableViewer.getControl().setFocus();
            fTableViewer.setSelection(selection);
        }
        checkPageCompletionStatus(displayErrors);
        updateButtonEnablement(fTableViewer.getSelection());
        updateStatusLine();
    }
}