/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.dltk.javascript.internal.ui.refactoring;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.internal.javascript.corext.refactoring.ParameterInfo;
import org.eclipse.dltk.internal.ui.dialogs.TableTextCellEditor;
import org.eclipse.dltk.internal.ui.dialogs.TextFieldNavigationHandler;
import org.eclipse.dltk.internal.ui.refactoring.RefactoringMessages;
import org.eclipse.dltk.internal.ui.util.SWTUtil;
import org.eclipse.dltk.internal.ui.util.TableLayoutComposite;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableFontProvider;
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.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Font;
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.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

/**
 * A special control to edit and reorder method parameters.
 */
public class ChangeParametersControl extends Composite {
	public enum Mode {
		EXTRACT_METHOD, CHANGE_METHOD_SIGNATURE, INTRODUCE_PARAMETER;
		/*
		 * private final String fName; private Mode(String name) { fName= name;
		 * } public static final Mode EXTRACT_METHOD= new
		 * Mode("EXTRACT_METHOD"); //$NON-NLS-1$ public static final Mode
		 * CHANGE_METHOD_SIGNATURE= new Mode("CHANGE_METHOD_SIGNATURE");
		 * //$NON-NLS-1$ public static final Mode INTRODUCE_PARAMETER= new
		 * Mode("INTRODUCE_PARAMETER"); //$NON-NLS-1$ public String toString() {
		 * return fName; }
		 */
		public boolean canChangeTypes() {
			return this == CHANGE_METHOD_SIGNATURE;
		}

		public boolean canAddParameters() {
			return this == Mode.CHANGE_METHOD_SIGNATURE;
		}

		public boolean canChangeDefault() {
			return this == Mode.CHANGE_METHOD_SIGNATURE;
		}
	}

	private static class ParameterInfoContentProvider implements
			IStructuredContentProvider {
		public Object[] getElements(Object inputElement) {
			return removeMarkedAsDeleted((List<ParameterInfo>) inputElement);
		}

		private ParameterInfo[] removeMarkedAsDeleted(
				List<ParameterInfo> paramInfos) {
			List<ParameterInfo> result = new ArrayList<ParameterInfo>(
					paramInfos.size());
			for (ParameterInfo info : paramInfos) {
				if (!info.isDeleted())
					result.add(info);
			}
			return result.toArray(new ParameterInfo[result.size()]);
		}

		public void dispose() {
			// do nothing
		}

		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			// do nothing
		}
	}

	private static class ParameterInfoLabelProvider extends LabelProvider
			implements ITableLabelProvider, ITableFontProvider {
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		public String getColumnText(Object element, int columnIndex) {
			ParameterInfo info = (ParameterInfo) element;
			switch (columnIndex) {
			// case TYPE_PROP:
			// return info.getNewTypeName();
			case NEWNAME_PROP:
				return info.getNewName();
			case DEFAULT_PROP:
				if (info.isAdded())
					return info.getDefaultValue();
				else
					return "-"; //$NON-NLS-1$
			default:
				throw new IllegalArgumentException(columnIndex + ": " + element); //$NON-NLS-1$
			}
		}

		public Font getFont(Object element, int columnIndex) {
			ParameterInfo info = (ParameterInfo) element;
			if (info.isAdded())
				return JFaceResources.getFontRegistry().getBold(
						JFaceResources.DIALOG_FONT);
			else
				return null;
		}
	}

	private class ParametersCellModifier implements ICellModifier {
		public boolean canModify(Object element, String property) {
			Assert.isTrue(element instanceof ParameterInfo);
			/*
			 * if (property.equals(PROPERTIES[TYPE_PROP])) return
			 * fMode.canChangeTypes(); else
			 */if (property.equals(PROPERTIES[NEWNAME_PROP]))
				return true;
			else if (property.equals(PROPERTIES[DEFAULT_PROP]))
				return (((ParameterInfo) element).isAdded());
			Assert.isTrue(false);
			return false;
		}

		public Object getValue(Object element, String property) {
			Assert.isTrue(element instanceof ParameterInfo);
			/*
			 * if (property.equals(PROPERTIES[TYPE_PROP])) return
			 * ((ParameterInfo) element).getNewTypeName(); else
			 */if (property.equals(PROPERTIES[NEWNAME_PROP]))
				return ((ParameterInfo) element).getNewName();
			else if (property.equals(PROPERTIES[DEFAULT_PROP]))
				return ((ParameterInfo) element).getDefaultValue();
			Assert.isTrue(false);
			return null;
		}

		public void modify(Object element, String property, Object value) {
			if (element instanceof TableItem)
				element = ((TableItem) element).getData();
			if (!(element instanceof ParameterInfo))
				return;
			boolean unchanged;
			ParameterInfo parameterInfo = (ParameterInfo) element;
			if (property.equals(PROPERTIES[NEWNAME_PROP])) {
				unchanged = parameterInfo.getNewName().equals(value);
				parameterInfo.setNewName((String) value);
			} else if (property.equals(PROPERTIES[DEFAULT_PROP])) {
				unchanged = parameterInfo.getDefaultValue().equals(value);
				parameterInfo.setDefaultValue((String) value);
				/*
				 * } else if (property.equals(PROPERTIES[TYPE_PROP])) {
				 * unchanged= parameterInfo.getNewTypeName().equals(value);
				 * parameterInfo.setNewTypeName((String) value);
				 */
			} else {
				throw new IllegalStateException();
			}
			if (!unchanged) {
				ChangeParametersControl.this.fListener
						.parameterChanged(parameterInfo);
				ChangeParametersControl.this.fTableViewer.update(parameterInfo,
						new String[] { property });
			}
		}
	}

	private static final String[] PROPERTIES = { /* "type", */"new", "default" }; //$NON-NLS-2$ //$NON-NLS-1$ //$NON-NLS-3$
	// private static final int TYPE_PROP= 0;
	private static final int NEWNAME_PROP = 0;
	private static final int DEFAULT_PROP = 1;

	private static final int ROW_COUNT = 7;

	private final Mode fMode;
	private final IParameterListChangeListener fListener;
	private List<ParameterInfo> fParameterInfos;
	/*
	 * private final StubTypeContext fTypeContext; private final String[]
	 * fParamNameProposals; private ContentAssistHandler
	 * fNameContentAssistHandler;
	 */

	private TableViewer fTableViewer;
	private Button fUpButton;
	private Button fDownButton;
	private Button fEditButton;
	private Button fAddButton;
	private Button fRemoveButton;

	/*
	 * public ChangeParametersControl(Composite parent, int style, String label,
	 * IParameterListChangeListener listener, Mode mode, StubTypeContext
	 * typeContext) { this(parent, style, label, listener, mode, typeContext,
	 * new String[0]); }
	 * 
	 * public ChangeParametersControl(Composite parent, int style, String label,
	 * IParameterListChangeListener listener, Mode mode) { this(parent, style,
	 * label, listener, mode, null, new String[0]); }
	 * 
	 * public ChangeParametersControl(Composite parent, int style, String label,
	 * IParameterListChangeListener listener, Mode mode, String[]
	 * paramNameProposals) { this(parent, style, label, listener, mode, null,
	 * paramNameProposals); }
	 */

	/**
	 * @param label
	 *            the label before the table or <code>null</code>
	 * @param typeContext
	 *            the package in which to complete types
	 */
	public ChangeParametersControl(Composite parent, int style, String label,
			IParameterListChangeListener listener, Mode mode/*
															 * , StubTypeContext
															 * typeContext
															 */) {
		super(parent, style);
		Assert.isNotNull(listener);
		fListener = listener;
		fMode = mode;
		// fTypeContext= typeContext;
		// fParamNameProposals= paramNameProposals;

		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		setLayout(layout);

		if (label != null) {
			Label tableLabel = new Label(this, SWT.NONE);
			GridData labelGd = new GridData();
			labelGd.horizontalSpan = 2;
			tableLabel.setLayoutData(labelGd);
			tableLabel.setText(label);
		}

		createParameterList(this);
		createButtonComposite(this);
	}

	public void setInput(List<ParameterInfo> parameterInfos) {
		Assert.isNotNull(parameterInfos);
		fParameterInfos = parameterInfos;
		fTableViewer.setInput(fParameterInfos);
		if (fParameterInfos.size() > 0)
			fTableViewer.setSelection(new StructuredSelection(fParameterInfos
					.get(0)));
	}

	public void editParameter(ParameterInfo info) {
		fTableViewer.getControl().setFocus();
		if (!info.isDeleted()) {
			fTableViewer.setSelection(new StructuredSelection(info), true);
			updateButtonsEnabledState();
			editColumnOrNextPossible(NEWNAME_PROP);
			return;
		}
	}

	// ---- Parameter table
	// -----------------------------------------------------------------------------------

	private void createParameterList(Composite parent) {
		TableLayoutComposite layouter = new TableLayoutComposite(parent,
				SWT.NONE);
		addColumnLayoutData(layouter);

		final Table table = new Table(layouter, SWT.MULTI | SWT.BORDER
				| SWT.FULL_SELECTION);
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		TableColumn tc;
		// tc= new TableColumn(table, SWT.NONE, TYPE_PROP);
		// tc.setResizable(true);
		// tc.setText(RefactoringMessages.ChangeParametersControl_table_type);

		tc = new TableColumn(table, SWT.NONE, NEWNAME_PROP);
		tc.setResizable(true);
		tc.setText(RefactoringMessages.ChangeParametersControl_table_name);

		if (fMode.canChangeDefault()) {
			tc = new TableColumn(table, SWT.NONE, DEFAULT_PROP);
			tc.setResizable(true);
			tc.setText(RefactoringMessages.ChangeParametersControl_table_defaultValue);
		}

		GridData gd = new GridData(GridData.FILL_BOTH);
		gd.heightHint = SWTUtil.getTableHeightHint(table, ROW_COUNT);
		gd.widthHint = 40;
		layouter.setLayoutData(gd);

		fTableViewer = new TableViewer(table);
		fTableViewer.setUseHashlookup(true);
		fTableViewer.setContentProvider(new ParameterInfoContentProvider());
		fTableViewer.setLabelProvider(new ParameterInfoLabelProvider());
		fTableViewer
				.addSelectionChangedListener(new ISelectionChangedListener() {
					public void selectionChanged(SelectionChangedEvent event) {
						updateButtonsEnabledState();
					}
				});

		table.addTraverseListener(new TraverseListener() {
			public void keyTraversed(TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_RETURN && e.stateMask == SWT.NONE) {
					editColumnOrNextPossible(0);
					e.detail = SWT.TRAVERSE_NONE;
				}
			}
		});
		table.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.F2 && e.stateMask == SWT.NONE) {
					editColumnOrNextPossible(0);
					e.doit = false;
				}
			}
		});

		addCellEditors();
	}

	private void editColumnOrNextPossible(int column) {
		ParameterInfo[] selected = getSelectedElements();
		if (selected.length != 1)
			return;
		int nextColumn = column;
		do {
			fTableViewer.editElement(selected[0], nextColumn);
			if (fTableViewer.isCellEditorActive())
				return;
			nextColumn = nextColumn(nextColumn);
		} while (nextColumn != column);
	}

	private void editColumnOrPrevPossible(int column) {
		ParameterInfo[] selected = getSelectedElements();
		if (selected.length != 1)
			return;
		int prevColumn = column;
		do {
			fTableViewer.editElement(selected[0], prevColumn);
			if (fTableViewer.isCellEditorActive())
				return;
			prevColumn = prevColumn(prevColumn);
		} while (prevColumn != column);
	}

	private int nextColumn(int column) {
		return (column >= getTable().getColumnCount() - 1) ? 0 : column + 1;
	}

	private int prevColumn(int column) {
		return (column <= 0) ? getTable().getColumnCount() - 1 : column - 1;
	}

	private void addColumnLayoutData(TableLayoutComposite layouter) {
		if (fMode.canChangeDefault()) {
			// layouter.addColumnData(new ColumnWeightData(33, true));
			layouter.addColumnData(new ColumnWeightData(33, true));
			layouter.addColumnData(new ColumnWeightData(34, true));
		} else {
			// layouter.addColumnData(new ColumnWeightData(50, true));
			layouter.addColumnData(new ColumnWeightData(50, true));
		}
	}

	private ParameterInfo[] getSelectedElements() {
		ISelection selection = fTableViewer.getSelection();
		if (selection == null)
			return new ParameterInfo[0];

		if (!(selection instanceof IStructuredSelection))
			return new ParameterInfo[0];

		List<ParameterInfo> selected = ((IStructuredSelection) selection)
				.toList();
		return (ParameterInfo[]) selected.toArray(new ParameterInfo[selected
				.size()]);
	}

	// ---- Button bar
	// --------------------------------------------------------------------------------------

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

		if (fMode.canAddParameters())
			fAddButton = createAddButton(buttonComposite);

		fEditButton = createEditButton(buttonComposite);

		if (fMode.canAddParameters())
			fRemoveButton = createRemoveButton(buttonComposite);

		if (buttonComposite.getChildren().length != 0)
			addSpacer(buttonComposite);

		fUpButton = createButton(buttonComposite,
				RefactoringMessages.ChangeParametersControl_buttons_move_up,
				true);
		fDownButton = createButton(buttonComposite,
				RefactoringMessages.ChangeParametersControl_buttons_move_down,
				false);

		updateButtonsEnabledState();
	}

	private void addSpacer(Composite parent) {
		Label label = new Label(parent, SWT.NONE);
		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.heightHint = 5;
		label.setLayoutData(gd);
	}

	private void updateButtonsEnabledState() {
		fUpButton.setEnabled(canMove(true));
		fDownButton.setEnabled(canMove(false));
		if (fEditButton != null)
			fEditButton.setEnabled(getTableSelectionCount() == 1);
		if (fAddButton != null)
			fAddButton.setEnabled(true);
		if (fRemoveButton != null)
			fRemoveButton.setEnabled(getTableSelectionCount() != 0);
	}

	private int getTableSelectionCount() {
		return getTable().getSelectionCount();
	}

	private int getTableItemCount() {
		return getTable().getItemCount();
	}

	private Table getTable() {
		return fTableViewer.getTable();
	}

	private Button createEditButton(Composite buttonComposite) {
		Button button = new Button(buttonComposite, SWT.PUSH);
		button.setText(RefactoringMessages.ChangeParametersControl_buttons_edit);
		button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		SWTUtil.setButtonDimensionHint(button);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				try {
					ParameterInfo[] selected = getSelectedElements();
					Assert.isTrue(selected.length == 1);
					ParameterInfo parameterInfo = selected[0];
					ParameterEditDialog dialog = new ParameterEditDialog(
							getShell(), parameterInfo, fMode.canChangeTypes(),
							fMode.canChangeDefault()/* , fTypeContext */);
					dialog.open();
					fListener.parameterChanged(parameterInfo);
					fTableViewer.update(parameterInfo, PROPERTIES);
				} finally {
					fTableViewer.getControl().setFocus();
				}
			}
		});
		return button;
	}

	private Button createAddButton(Composite buttonComposite) {
		Button button = new Button(buttonComposite, SWT.PUSH);
		button.setText(RefactoringMessages.ChangeParametersControl_buttons_add);
		button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		SWTUtil.setButtonDimensionHint(button);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				String[] excludedParamNames = new String[fParameterInfos.size()];
				for (int i = 0; i < fParameterInfos.size(); i++) {
					ParameterInfo info = (ParameterInfo) fParameterInfos.get(i);
					excludedParamNames[i] = info.getNewName();
				}
				// IJavaProject javaProject=
				// fTypeContext.getCuHandle().getJavaProject();
				// String newParamName=
				// StubUtility.suggestArgumentName(javaProject,
				// RefactoringMessages.ChangeParametersControl_new_parameter_default_name,
				// excludedParamNames);
				ParameterInfo newInfo = ParameterInfo
						.createInfoForAddedParameter("", "", "undefined"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				int insertIndex = fParameterInfos.size();
				for (int i = fParameterInfos.size() - 1; i >= 0; i--) {
					ParameterInfo info = (ParameterInfo) fParameterInfos.get(i);
					/*
					 * if (info.isNewVarargs()) { insertIndex= i; break; }
					 */
				}
				fParameterInfos.add(insertIndex, newInfo);
				fListener.parameterAdded(newInfo);
				fTableViewer.refresh();
				fTableViewer.getControl().setFocus();
				fTableViewer.setSelection(new StructuredSelection(newInfo),
						true);
				updateButtonsEnabledState();
				editColumnOrNextPossible(0);
			}
		});
		return button;
	}

	private Button createRemoveButton(Composite buttonComposite) {
		final Button button = new Button(buttonComposite, SWT.PUSH);
		button.setText(RefactoringMessages.ChangeParametersControl_buttons_remove);
		button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		SWTUtil.setButtonDimensionHint(button);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				int index = getTable().getSelectionIndices()[0];
				ParameterInfo[] selected = getSelectedElements();
				for (int i = 0; i < selected.length; i++) {
					if (selected[i].isAdded())
						fParameterInfos.remove(selected[i]);
					else
						selected[i].markAsDeleted();
				}
				restoreSelection(index);
			}

			private void restoreSelection(int index) {
				fTableViewer.refresh();
				fTableViewer.getControl().setFocus();
				int itemCount = getTableItemCount();
				if (itemCount != 0) {
					if (index >= itemCount)
						index = itemCount - 1;
					getTable().setSelection(index);
				}
				fListener.parameterListChanged();
				updateButtonsEnabledState();
			}
		});
		return button;
	}

	private Button createButton(Composite buttonComposite, String text,
			final boolean up) {
		Button button = new Button(buttonComposite, SWT.PUSH);
		button.setText(text);
		button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		SWTUtil.setButtonDimensionHint(button);
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				ISelection savedSelection = fTableViewer.getSelection();
				if (savedSelection == null)
					return;
				ParameterInfo[] selection = getSelectedElements();
				if (selection.length == 0)
					return;

				if (up) {
					moveUp(selection);
				} else {
					moveDown(selection);
				}
				fTableViewer.refresh();
				fTableViewer.setSelection(savedSelection);
				fListener.parameterListChanged();
				fTableViewer.getControl().setFocus();
			}
		});
		return button;
	}

	// ---- editing
	// -----------------------------------------------------------------------------------------------

	private void addCellEditors() {
		fTableViewer.setColumnProperties(PROPERTIES);

		final TableTextCellEditor editors[] = new TableTextCellEditor[PROPERTIES.length];

		// editors[TYPE_PROP]= new TableTextCellEditor(fTableViewer, TYPE_PROP);
		editors[NEWNAME_PROP] = new TableTextCellEditor(fTableViewer,
				NEWNAME_PROP);
		editors[DEFAULT_PROP] = new TableTextCellEditor(fTableViewer,
				DEFAULT_PROP);

		/*
		 * if (fMode.canChangeTypes()) { SubjectControlContentAssistant
		 * assistant=
		 * installParameterTypeContentAssist(editors[TYPE_PROP].getText());
		 * editors[TYPE_PROP].setContentAssistant(assistant); } if
		 * (fParamNameProposals.length > 0) { SubjectControlContentAssistant
		 * assistant=
		 * installParameterNameContentAssist(editors[NEWNAME_PROP].getText());
		 * editors[NEWNAME_PROP].setContentAssistant(assistant); }
		 */

		for (int i = 0; i < editors.length; i++) {
			final int editorColumn = i;
			final TableTextCellEditor editor = editors[i];
			// support tabbing between columns while editing:
			editor.getText().addTraverseListener(new TraverseListener() {
				public void keyTraversed(TraverseEvent e) {
					switch (e.detail) {
					case SWT.TRAVERSE_TAB_NEXT:
						editColumnOrNextPossible(nextColumn(editorColumn));
						e.detail = SWT.TRAVERSE_NONE;
						break;

					case SWT.TRAVERSE_TAB_PREVIOUS:
						editColumnOrPrevPossible(prevColumn(editorColumn));
						e.detail = SWT.TRAVERSE_NONE;
						break;

					default:
						break;
					}
				}
			});
			TextFieldNavigationHandler.install(editor.getText());
		}

		/*
		 * editors[NEWNAME_PROP].setActivationListener(new
		 * TableTextCellEditor.IActivationListener(){ public void activate() {
		 * ParameterInfo[] selected= getSelectedElements(); if (selected.length
		 * == 1 && fNameContentAssistHandler != null) {
		 * fNameContentAssistHandler.setEnabled(selected[0].isAdded()); } } });
		 */

		fTableViewer.setCellEditors(editors);
		fTableViewer.setCellModifier(new ParametersCellModifier());
	}

	/*
	 * private SubjectControlContentAssistant
	 * installParameterTypeContentAssist(Text text) {
	 * JavaTypeCompletionProcessor processor= new
	 * JavaTypeCompletionProcessor(true, false); if (fTypeContext == null)
	 * processor.setCompletionContext(null, null, null); else
	 * processor.setCompletionContext(fTypeContext.getCuHandle(),
	 * fTypeContext.getBeforeString(), fTypeContext.getAfterString());
	 * SubjectControlContentAssistant contentAssistant=
	 * ControlContentAssistHelper.createJavaContentAssistant(processor);
	 * ContentAssistHandler.createHandlerForText(text, contentAssistant); return
	 * contentAssistant; }
	 * 
	 * private SubjectControlContentAssistant
	 * installParameterNameContentAssist(Text text) { VariableNamesProcessor
	 * processor= new VariableNamesProcessor(fParamNameProposals);
	 * SubjectControlContentAssistant contentAssistant=
	 * ControlContentAssistHelper.createJavaContentAssistant(processor);
	 * fNameContentAssistHandler=
	 * ContentAssistHandler.createHandlerForText(text, contentAssistant); return
	 * contentAssistant; }
	 */

	// ---- change order
	// ----------------------------------------------------------------------------------------

	private void moveUp(ParameterInfo[] selection) {
		moveUp(fParameterInfos, Arrays.asList(selection));
	}

	private void moveDown(ParameterInfo[] selection) {
		Collections.reverse(fParameterInfos);
		moveUp(fParameterInfos, Arrays.asList(selection));
		Collections.reverse(fParameterInfos);
	}

	private static void moveUp(List<ParameterInfo> elements,
			List<ParameterInfo> move) {
		List<ParameterInfo> res = new ArrayList<ParameterInfo>(elements.size());
		List<ParameterInfo> deleted = new ArrayList<ParameterInfo>();
		ParameterInfo floating = null;
		for (ParameterInfo curr : elements) {
			if (move.contains(curr)) {
				res.add(curr);
			} else if (((ParameterInfo) curr).isDeleted()) {
				deleted.add(curr);
			} else {
				if (floating != null)
					res.add(floating);
				floating = curr;
			}
		}
		if (floating != null) {
			res.add(floating);
		}
		res.addAll(deleted);
		elements.clear();
		for (ParameterInfo element : res) {
			elements.add(element);
		}
	}

	private boolean canMove(boolean up) {
		int notDeletedInfosCount = getNotDeletedInfosCount();
		if (notDeletedInfosCount == 0)
			return false;
		int[] indc = getTable().getSelectionIndices();
		if (indc.length == 0)
			return false;
		int invalid = up ? 0 : notDeletedInfosCount - 1;
		for (int i = 0; i < indc.length; i++) {
			if (indc[i] == invalid)
				return false;
		}
		return true;
	}

	private int getNotDeletedInfosCount() {
		if (fParameterInfos == null) // during initialization
			return 0;
		int result = 0;
		for (ParameterInfo info : fParameterInfos) {
			if (!info.isDeleted())
				result++;
		}
		return result;
	}
}
