/*******************************************************************************
 * 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.team.internal.ccvs.ui.wizards;


import java.text.Collator;  // don't use ICU, pending resolution of issue 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Group;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.eclipse.team.internal.ccvs.core.client.Command.KSubstOption;
import org.eclipse.team.internal.ccvs.core.util.StringMatcher;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.wizards.ModeWizard.ModeChange;
import org.eclipse.team.internal.ui.PixelConverter;
import org.eclipse.team.internal.ui.SWTUtils;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchLabelProvider;

//TODO: Filtering the TableViewer is currently slow for large amounts of files. 3.1M5 will feature a framework to help with this, so wait until it is there.
//TODO: Files should be added to the viewer asynchronously, currently bringing up the dialog takes a lot of time for large selections (e.g. jdt.ui)

public class ModeWizardSelectionPage extends WizardPage {
	
	private final static class ModeChangeCellModifier implements ICellModifier {
		
		private final ModeChangeTable fTable;
		
		public ModeChangeCellModifier(ModeChangeTable table) {
			fTable= table;
		}
		
		public boolean canModify(Object element, String property) {
			return PROPERTY_MODE.equals(property);
		}
		
		public Object getValue(Object element, String property) {
			if (PROPERTY_MODE.equals(property)) {
				final KSubstOption mode= ((ModeChange)element).getNewMode();
				for (int i = 0; i < MODES.length; i++) {
					if (MODES[i].equals(mode)) {
						return Integer.valueOf(i);
					}
				}
			}
			return null;
		}
		
		public void modify(Object element, String property, Object value) {
			if (element instanceof Item)
				element= ((Item)element).getData();
			if (PROPERTY_MODE.equals(property)) {
				((ModeChange)element).setNewMode(MODES[((Integer)value).intValue()]);
				fTable.modelChanged(true);
			}
		}
	}
	
	private final static class ModeChangeLabelProvider implements ITableLabelProvider {
		
		private final DecoratingLabelProvider fDecoratingLP;
		private final ModeChangeTable fTable;
		
		public ModeChangeLabelProvider(ModeChangeTable table) {
			fTable= table;
			fDecoratingLP= new DecoratingLabelProvider(new WorkbenchLabelProvider(), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator());
			fDecoratingLP.addListener(fTable);
		}
		
		public Image getColumnImage(Object element, int columnIndex) {
			if (columnIndex == INDEX_FILE) {
				return fDecoratingLP.getImage(((ModeChange)element).getFile());
			}
			return null;
		}
		
		public String getColumnText(Object element, int columnIndex) {
			final ModeChange change= (ModeChange)element;
			switch (columnIndex) {
			case INDEX_FILE: return (change.hasChanged() ? "* " : "") + change.getFile().getName(); //$NON-NLS-1$ //$NON-NLS-2$
			case INDEX_MODE: return change.getNewMode().getLongDisplayText();
			case INDEX_PATH: return change.getFile().getFullPath().toOSString();
			}
			throw new IllegalArgumentException();
		}
		
		public void addListener(ILabelProviderListener listener) {
		}
		
		public boolean isLabelProperty(Object element, String property) {
			return false;
		}
		
		public void dispose() {
			fDecoratingLP.removeListener(fTable);
		}
		
		public void removeListener(ILabelProviderListener listener) {        
		}
	}
	
	private final static class TableComparator extends ViewerComparator implements SelectionListener {
		
		private final Collator fCollator;
		private final TableViewer fViewer;
		private final TableColumn fFile, fMode, fPath;
		
		private int fIndex;
		private boolean fAscending;
		
		
		public TableComparator(TableViewer viewer, TableColumn fileColumn, TableColumn modeColumn, TableColumn pathColumn) {
//			TODO: possible issue, TableSorter's Collator not shared with base class.  Might cause problem switching to ICU collation.
			fCollator= Collator.getInstance();
			fViewer= viewer;
			
			fFile= fileColumn;
			fMode= modeColumn;
			fPath= pathColumn;
			
//			Set initial sorting to file column
			fIndex= INDEX_FILE;
			fViewer.getTable().setSortColumn(fFile);
			fViewer.getTable().setSortDirection(SWT.DOWN);
			fAscending= true;
			
			fileColumn.addSelectionListener(this);
			modeColumn.addSelectionListener(this);
			pathColumn.addSelectionListener(this);
		}
		
		public int compare(Viewer viewer, Object e1, Object e2) {
			
			final ModeChange mc1= (ModeChange)e1;
			final ModeChange mc2= (ModeChange)e2;
			
			final String s1, s2;
			
			switch (fIndex) {
			
			case INDEX_FILE: 
				s1= mc1.getFile().getName();
				s2= mc2.getFile().getName();
				break;
				
			case INDEX_MODE:
				s1= mc1.getNewMode().getLongDisplayText();
				s2= mc2.getNewMode().getLongDisplayText(); 
				break;
				
			case INDEX_PATH: 
				s1= mc1.getFile().getFullPath().toOSString();
				s2= mc2.getFile().getFullPath().toOSString(); 
				break;
				
			default: 
				throw new IllegalArgumentException();
			}
			
			final int compare= fCollator.compare(s1, s2);
			return fAscending ? compare : -compare;
		}
		
		public void widgetSelected(SelectionEvent e) {
			final int index= columnToIndex(e.widget);
			if (index == fIndex) {
				fIndex= index;
				fAscending= !fAscending;
				fViewer.getTable().setSortDirection(fAscending ? SWT.DOWN : SWT.UP);
			} else {
				fIndex= index;
				TableColumn tableCol = null;
				switch(fIndex){
					case INDEX_FILE:
						tableCol = fFile;
					break;
					
					case INDEX_MODE:
						tableCol = fMode;
					break;
					
					case INDEX_PATH:
						tableCol = fPath;
					break;
				}
				fViewer.getTable().setSortColumn(tableCol);
				fViewer.getTable().setSortDirection(fAscending ? SWT.DOWN : SWT.UP);
			}
			fViewer.refresh();
		}
		
		public void widgetDefaultSelected(SelectionEvent e) {
			// nop
		}
		
		private int columnToIndex(Object column) {
			if (column == fFile) return INDEX_FILE;
			if (column == fMode) return INDEX_MODE;
			if (column == fPath) return INDEX_PATH;
			throw new IllegalArgumentException();
		}
	}
	
	private static final class ModeChangeTable extends Observable implements ISelectionChangedListener, ILabelProviderListener {
		
		private final List fChanges;
		private final TableViewer fViewer;
		private final Filter fFilter;
		private int fNumberOfChanges;
		
		public ModeChangeTable(Composite composite, PixelConverter converter, List changes) {
			
			fChanges= changes;
			fNumberOfChanges= 0;
			
			/**
			 * Create a table.
			 */
			final Table table = new Table(composite, SWT.V_SCROLL | SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
			table.setLayoutData(SWTUtils.createHVFillGridData());
			table.setLinesVisible(false);
			table.setHeaderVisible(true);
			
			/**
			 * The 'File' column
			 */
			final TableColumn fileColumn = new TableColumn(table, SWT.NONE, INDEX_FILE);
			fileColumn.setWidth(converter.convertWidthInCharsToPixels(LARGE_COLUMN));
			fileColumn.setText(CVSUIMessages.ModeWizardSelectionPage_2); 
			table.setSortColumn(fileColumn);
			table.setSortDirection(SWT.DOWN);
			/**
			 * The 'Mode' column
			 */
			final TableColumn newModeColumn = new TableColumn(table, SWT.NONE, INDEX_MODE);
			newModeColumn.setWidth(converter.convertWidthInCharsToPixels(COLUMN_MIN_WIDTH_IN_CHARS + 6));
			newModeColumn.setText(CVSUIMessages.ModeWizardSelectionPage_3); 
			
			/**
			 * The 'Path' column
			 */
			final TableColumn pathColumn= new TableColumn(table, SWT.NONE, INDEX_PATH);
			pathColumn.setWidth(converter.convertWidthInCharsToPixels(50));
			pathColumn.setText(CVSUIMessages.ModeWizardSelectionPage_4); 
			
			
			fViewer= new TableViewer(table);
			fViewer.setContentProvider(new ModeChangeContentProvider());
			fViewer.setLabelProvider(new ModeChangeLabelProvider(this));
			fViewer.getControl().setLayoutData(SWTUtils.createHVFillGridData());
			
			final CellEditor newModeEditor = new ComboBoxCellEditor(table, COMBO_TEXT, SWT.READ_ONLY);
			
			fViewer.setCellEditors(new CellEditor [] { null, newModeEditor, null });
			fViewer.setColumnProperties(new String [] { PROPERTY_FILE, PROPERTY_MODE, PROPERTY_CHANGED });
			fViewer.setCellModifier(new ModeChangeCellModifier(this));
			
			fViewer.addFilter(fFilter= new Filter());
			
			fViewer.setComparator(new TableComparator(fViewer, fileColumn, newModeColumn, pathColumn));
			
			fViewer.setInput(fChanges);
			
			//TODO: CVSLightweightDecorator.decorate() is lighter than normal decs.
			fViewer.addSelectionChangedListener(this);
			
			fileColumn.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					
				}
			});
			
			fViewer.refresh();
		}
		
		public TableViewer getViewer() {
			return fViewer;
		}
		
		public void selectionChanged(SelectionChangedEvent event) {
			setChanged();
			notifyObservers(fViewer.getSelection());
		}
		
		public void modelChanged(boolean updateLabels) {
			fViewer.refresh(updateLabels);
			fNumberOfChanges= 0;
			for (Iterator iter = fChanges.iterator(); iter.hasNext();) {
				ModeChange change = (ModeChange) iter.next();
				if (change.hasChanged())
					++fNumberOfChanges;
			}
			setChanged();
			notifyObservers();
		}
		
		public Filter getFilter() {
			return fFilter;
		}
		
		public IStructuredSelection getSelection() {
			return (IStructuredSelection)fViewer.getSelection();
		}
		
		public void labelProviderChanged(LabelProviderChangedEvent event) {
			fViewer.refresh();
		}
		
		public void selectAll() {
			fViewer.setSelection(new StructuredSelection(fChanges));
			fViewer.getControl().setFocus();
		}
		
		public void selectNone() {
			fViewer.setSelection(StructuredSelection.EMPTY);
			fViewer.getControl().setFocus();
		}
		
		public int getNumberOfChanges() {
			return fNumberOfChanges;
		}
	}
	
	private static final class ModeChangeContentProvider implements IStructuredContentProvider {
		
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		}
		
		public Object[] getElements(Object inputElement) {
//			new FetchJob(fViewer, (List)inputElement, fPattern);
//			return new Object[0];
			return ((List)inputElement).toArray();
		}
		
		public void dispose() {
		}
	}
	
	private static final class ModeCombo extends SelectionAdapter implements Observer {
		
		private final Combo fCombo;
		private final ModeChangeTable fTable;
		
		public ModeCombo(ModeChangeTable table, Composite parent) {
			fTable= table;
			fCombo= new Combo(parent, SWT.READ_ONLY);
			fCombo.setLayoutData(SWTUtils.createHFillGridData());
			fCombo.setItems(COMBO_TEXT);
			fCombo.addSelectionListener(this);
			fTable.addObserver(this);
		}
		
		public void widgetSelected(SelectionEvent e) {
			final KSubstOption mode= MODES[fCombo.getSelectionIndex()];
			final IStructuredSelection selection= fTable.getSelection();
			for (final Iterator iter = selection.iterator(); iter.hasNext();) {
				final ModeChange change = (ModeChange) iter.next();
				change.setNewMode(mode);                
			}
			fTable.modelChanged(true);
		}
		
		public void update(Observable o, Object arg) {
			final IStructuredSelection selection= (IStructuredSelection)fTable.getViewer().getSelection();
			
			if (selection.isEmpty()) {
				fCombo.deselectAll();
				fCombo.setEnabled(false);
			} else {
				fCombo.setEnabled(true);
				final KSubstOption option= ((ModeChange)selection.getFirstElement()).getNewMode();
				for (Iterator iter = selection.iterator(); iter.hasNext();) {
					if (option != ((ModeChange)iter.next()).getNewMode()) {
						fCombo.deselectAll();
						return;
					}
				}
				fCombo.setText(option.getLongDisplayText());
			}
		}
	}
	
	private static final class Filter extends ViewerFilter {
		
		private boolean fFilterUnchanged;
		private StringMatcher fMatcher;
		
		public Filter() {
			fFilterUnchanged= false;
			fMatcher= new StringMatcher("*", true, false); //$NON-NLS-1$
		}
		
		public boolean select(Viewer viewer, Object parentElement, Object element) {
			final ModeChange change= (ModeChange)element;
			if (fFilterUnchanged && !change.hasChanged())
				return false;
			if (!fMatcher.match(change.getFile().getName()))
				return false;
			return true;
		}
		
		public void setPattern(String pattern) {
			pattern= pattern.trim();
			if (!pattern.endsWith("*")) { //$NON-NLS-1$
				pattern += "*"; //$NON-NLS-1$
			}
			fMatcher= new StringMatcher(pattern, true, false);
		}
		
		public void filterUnchanged(boolean filter) {
			fFilterUnchanged= filter;
		}
	}
	
	private static final class ResetButton extends SelectionAdapter implements Observer {
		
		private final ModeChangeTable fTable;
		private final Button fButton;
		
		public ResetButton(ModeChangeTable table, Composite parent, PixelConverter converter) {
			final int buttonWidth= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			fTable= table;
			fButton= new Button(parent, SWT.NONE);
			fButton.setLayoutData(SWTUtils.createGridData(buttonWidth, SWT.DEFAULT, SWT.FILL, SWT.CENTER, false, false));
			fButton.setText(CVSUIMessages.ModeWizardSelectionPage_8); 
			fButton.setToolTipText(CVSUIMessages.ModeWizardSelectionPage_9); 
			fButton.addSelectionListener(this);
			fTable.addObserver(this);
		}
		
		public void widgetSelected(SelectionEvent e) {
			fButton.setEnabled(false);
			final IStructuredSelection selection= fTable.getSelection();
			for (Iterator iter = selection.iterator(); iter.hasNext();) {
				final ModeChange change = (ModeChange) iter.next();
				change.setNewMode(change.getMode());
			}
			fTable.modelChanged(true);
		}
		
		public void update(Observable o, Object arg) {
			final IStructuredSelection selection= fTable.getSelection();
			for (final Iterator iter = selection.iterator(); iter.hasNext();) {
				if (((ModeChange)iter.next()).hasChanged()) {
					fButton.setEnabled(true);
					return;
				}
			}
			fButton.setEnabled(false);
		}
	}
	
	private static final class GuessButton extends SelectionAdapter implements Observer {
		
		private final ModeChangeTable fTable;
		private final Button fButton;
		
		public GuessButton(ModeChangeTable table, Composite parent, PixelConverter converter) {
			fTable= table;
			final int buttonWidth= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			fButton= new Button(parent, SWT.NONE);
			fButton.setLayoutData(SWTUtils.createGridData(buttonWidth, SWT.DEFAULT, SWT.FILL, SWT.CENTER, false, false));
			fButton.setText(CVSUIMessages.ModeWizardSelectionPage_10); 
			fButton.setToolTipText(CVSUIMessages.ModeWizardSelectionPage_11); 
			fButton.addSelectionListener(this);
			fTable.addObserver(this);
			
		}
		
		public void widgetSelected(SelectionEvent e) {
			final IStructuredSelection selection= fTable.getSelection();
			for (Iterator iter = selection.iterator(); iter.hasNext();) {
				final ModeChange change = (ModeChange) iter.next();
				change.setNewMode(KSubstOption.fromFile(change.getFile()));
			}
			fTable.modelChanged(true);
		}
		
		public void update(Observable o, Object arg) {
			fButton.setEnabled(!fTable.getSelection().isEmpty());
		}
	}     
	
	private static final class SelectAllButton extends SelectionAdapter {
		
		private final ModeWizardSelectionPage fPage;
		private final Button fButton;
		
		public SelectAllButton(ModeWizardSelectionPage page, Composite parent, PixelConverter converter) {
			fPage= page;
			final int buttonWidth= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			fButton= new Button(parent, SWT.NONE);
			fButton.setLayoutData(SWTUtils.createGridData(buttonWidth, SWT.DEFAULT, SWT.FILL, SWT.CENTER, false, false));
			fButton.setText(CVSUIMessages.ModeWizardSelectionPage_12); 
			fButton.addSelectionListener(this);
		}
		
		public void widgetSelected(SelectionEvent e) {
			fPage.getTable().selectAll();
		}
	}     
	
	private static final class SelectNoneButton extends SelectionAdapter {
		
		private final ModeWizardSelectionPage fPage;
		private final Button fButton;
		
		public SelectNoneButton(ModeWizardSelectionPage page, Composite parent, PixelConverter converter) {
			fPage= page;
			final int buttonWidth= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			fButton= new Button(parent, SWT.NONE);
			fButton.setLayoutData(SWTUtils.createGridData(buttonWidth, SWT.DEFAULT, SWT.FILL, SWT.CENTER, false, false));
			fButton.setText(CVSUIMessages.ModeWizardSelectionPage_13); 
			fButton.addSelectionListener(this);
		}
		
		public void widgetSelected(SelectionEvent e) {
			fPage.getTable().selectNone();
		}
	}     
	
	private static final class ShowChangesOnlyCheckbox extends SelectionAdapter {
		
		private final ModeWizardSelectionPage fPage;
		private final Button fCheck;
		
		public ShowChangesOnlyCheckbox(ModeWizardSelectionPage page, Composite parent) {
			fPage= page;
			fCheck= new Button(parent, SWT.CHECK);
			fCheck.setText(CVSUIMessages.ModeWizardSelectionPage_14); 
			fCheck.setLayoutData(SWTUtils.createHFillGridData());
			fCheck.setSelection(false);
			fCheck.addSelectionListener(this);
		}
		
		public void widgetSelected(SelectionEvent e) {
			final ModeChangeTable table= fPage.getTable();
			table.getFilter().filterUnchanged(fCheck.getSelection());
			table.modelChanged(true);
		}
	}
	
	private static final class FilterTextBox extends SelectionAdapter implements ModifyListener {
		private final ModeWizardSelectionPage fPage;
		private final Text fTextField;
		
		public FilterTextBox(ModeWizardSelectionPage page, Composite parent, PixelConverter converter) {
			fPage= page;
			fTextField= new Text(parent, SWT.SINGLE | SWT.BORDER);
			fTextField.setLayoutData(SWTUtils.createHFillGridData());
			
			final int buttonWidth= converter.convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH);
			final Button button= new Button(parent, SWT.PUSH);
			button.setText(CVSUIMessages.ModeWizardSelectionPage_15); 
			button.setLayoutData(SWTUtils.createGridData(buttonWidth, SWT.DEFAULT, SWT.FILL, SWT.CENTER, false, false));
			button.addSelectionListener(this);
			
			fTextField.addModifyListener(this);
		}
		
		public void widgetSelected(SelectionEvent e) {
			fTextField.setText(""); //$NON-NLS-1$
			fTextField.setFocus();
		}
		
		public void modifyText(ModifyEvent e) {
			final ModeChangeTable table= fPage.getTable();
			table.getFilter().setPattern(fTextField.getText());
			table.modelChanged(false);
		}
		
		public void setFocus() {
			fTextField.setFocus();
		}
	}
	
	private static final class ChangeCounterLabel implements Observer {
		
		private final Label fLabel;
		private final ModeChangeTable fTable;
		
		ChangeCounterLabel(Composite parent, ModeChangeTable table) {
			fTable= table;
			fTable.addObserver(this);
			fLabel= SWTUtils.createLabel(parent, null);
			fLabel.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
		}
		
		public void update(Observable o, Object arg) {
			updateText(fTable.getNumberOfChanges());
		}
		
		/**
		 * @param numberOfChanges
		 */
		private void updateText(int numberOfChanges) {
			fLabel.setText(NLS.bind(CVSUIMessages.ModeWizardSelectionPage_17, new String[] { Integer.toString(numberOfChanges) })); 
		}

	}

	private static final class SelectionCounterLabel implements Observer {
		
		private final Label fLabel;
		private final ModeChangeTable fTable;
		
		public SelectionCounterLabel(Composite parent, ModeChangeTable table) {
			fTable= table;
			fTable.addObserver(this);
			fLabel= new Label(parent, SWT.WRAP | SWT.RIGHT);
			fLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
		}
		
		public void update(Observable o, Object arg) {
			updateText(fTable.getSelection().size());
		}
		
		/**
		 * @param numberOfChanges
		 */
		private void updateText(int selected) {
			fLabel.setText(NLS.bind(CVSUIMessages.ModeWizardSelectionPage_25, new String[] { Integer.toString(selected) })); 
		}
	}
	
	private final static int LARGE_COLUMN= 50;
	
	protected static final int INDEX_FILE= 0;
	protected static final int INDEX_MODE= 1;
	protected static final int INDEX_PATH= 2;
	
	protected static final String PROPERTY_FILE= "file"; //$NON-NLS-1$
	protected static final String PROPERTY_MODE= "mode"; //$NON-NLS-1$
	protected static final String PROPERTY_CHANGED= "changed"; //$NON-NLS-1$
	
	protected static final KSubstOption [] MODES;
	protected static final String [] COMBO_TEXT;
	
	static final int COLUMN_MIN_WIDTH_IN_CHARS;
	
	static {
		MODES= KSubstOption.getAllKSubstOptions();
		Arrays.sort(MODES, new Comparator() {
			public int compare(Object a, Object b) {
				String aKey = ((KSubstOption)a).getLongDisplayText();
				String bKey = ((KSubstOption) b).getLongDisplayText();
				return aKey.compareTo(bKey);
			}
		});
		COMBO_TEXT= new String[MODES.length];
		int maxLength= 0;
		for (int i = 0; i < MODES.length; i++) {
			COMBO_TEXT[i]= MODES[i].getLongDisplayText();
			if (COMBO_TEXT[i].length() > maxLength) maxLength= COMBO_TEXT[i].length();
		}
		COLUMN_MIN_WIDTH_IN_CHARS= maxLength;
	}
	
	private final List fChanges;
	protected ModeChangeTable fTable;
	
	private CommitCommentArea fCommentArea;
	
	public ModeWizardSelectionPage(List modeChanges) {
		super(CVSUIMessages.ModeWizardSelectionPage_18, CVSUIMessages.ModeWizardSelectionPage_19, CVSUIPlugin.getPlugin().getImageDescriptor(ICVSUIConstants.IMG_WIZBAN_KEYWORD)); // 
		setDescription(CVSUIMessages.ModeWizardSelectionPage_20); 
		fChanges= modeChanges;
	}
	
	public void createControl(final Composite parent) {
		
		final PixelConverter converter= SWTUtils.createDialogPixelConverter(parent);
		
		final int horizontalSpace= converter.convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
		final int verticalSpace= converter.convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
		
		/**
		 * The main composite with the vertical sash
		 */
		final Composite mainComposite= SWTUtils.createHVFillComposite(parent, SWTUtils.MARGINS_DEFAULT);
        // set F1 help
        PlatformUI.getWorkbench().getHelpSystem().setHelp(mainComposite, IHelpContextIds.KEYWORD_SUBSTITUTION_PAGE);
        
		final SashForm mainSash= new SashForm(mainComposite, SWT.VERTICAL);
		mainSash.setLayoutData(SWTUtils.createHVFillGridData());
		
		/**
		 * The composite with the filter box, the table and the selection and filter controls.
		 */
		final Composite topComposite= SWTUtils.createHVFillComposite(mainSash, SWTUtils.MARGINS_NONE);
		((GridLayout)topComposite.getLayout()).marginBottom= verticalSpace;
		
		final Composite topGroup= SWTUtils.createHVFillGroup(topComposite, CVSUIMessages.ModeWizardSelectionPage_21, SWTUtils.MARGINS_DIALOG); 
		
		final Composite filterComposite= SWTUtils.createHFillComposite(topGroup, SWTUtils.MARGINS_NONE, 2);
		final FilterTextBox filterBox= new FilterTextBox(ModeWizardSelectionPage.this, filterComposite, converter);
		
		fTable= new ModeChangeTable(topGroup, converter, fChanges);
		
		final Composite selectionComposite= SWTUtils.createHFillComposite(topGroup, SWTUtils.MARGINS_NONE, 2);

		new ChangeCounterLabel(selectionComposite, fTable);
		new SelectionCounterLabel(selectionComposite, fTable);
		
		new ShowChangesOnlyCheckbox(ModeWizardSelectionPage.this, selectionComposite);
		
		final Composite buttonComposite= SWTUtils.createHFillComposite(selectionComposite, SWTUtils.MARGINS_NONE, 2);
		buttonComposite.setLayoutData(new GridData());
		new SelectAllButton(ModeWizardSelectionPage.this, buttonComposite, converter);
		new SelectNoneButton(ModeWizardSelectionPage.this, buttonComposite, converter);
		
		/**
		 * The bottom sash which separates the mode controls from the commit comment area
		 */
		final SashForm bottomSash= new SashForm(mainSash, SWT.NONE);
		bottomSash.setLayoutData(SWTUtils.createHFillGridData());
		
		/**
		 * The left composite with the mode controls.
		 */
		final Composite leftComposite= SWTUtils.createHVFillComposite(bottomSash, SWTUtils.MARGINS_NONE, 1);
		((GridLayout)leftComposite.getLayout()).marginRight= horizontalSpace;
		((GridLayout)leftComposite.getLayout()).marginTop= verticalSpace;
		
		final Group leftGroup= SWTUtils.createHVFillGroup(leftComposite, CVSUIMessages.ModeWizardSelectionPage_22, SWTUtils.MARGINS_DIALOG, 3); 
		
		new ModeCombo(fTable, leftGroup);
		new GuessButton(fTable, leftGroup, converter);
		new ResetButton(fTable, leftGroup, converter);
		SWTUtils.createPlaceholder(leftGroup, 1);
		final Label infoLabel= SWTUtils.createLabel(leftGroup, CVSUIMessages.ModeWizardSelectionPage_23, 3); 
		
		fTable.addObserver(new Observer() {
			public void update(Observable o, Object arg) {
				final boolean enabled= !fTable.getSelection().isEmpty();
				leftGroup.setEnabled(enabled);
				infoLabel.setEnabled(enabled);
			}
		});
		
		/**
		 * The right composite with the commit comment area.
		 */
		final Composite rightComposite= SWTUtils.createHVFillComposite(bottomSash, SWTUtils.MARGINS_NONE);
		((GridLayout)rightComposite.getLayout()).marginLeft= horizontalSpace;
		((GridLayout)rightComposite.getLayout()).marginTop= verticalSpace;
		
		final Group rightGroup= SWTUtils.createHVFillGroup(rightComposite, CVSUIMessages.ModeWizardSelectionPage_24, SWTUtils.MARGINS_DIALOG); 
		(fCommentArea= new CommitCommentArea()).createArea(rightGroup);
		
		/**
		 * Set up the page
		 */
		mainSash.setWeights(new int [] { 5, 2 });
		bottomSash.setWeights(new int [] { 3, 2 });
		fTable.modelChanged(true);
		fTable.selectAll();
		filterBox.setFocus();
		setupListeners();
		setControl(mainComposite);
		validatePage();
	}

	private void setupListeners() {
		fCommentArea.addPropertyChangeListener(new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				if (event.getProperty() != null) {
					validatePage();
				}
			}
		});
	}

	protected ModeChangeTable getTable() {
		return fTable;
	}
	
	public List getChanges() {
		final List changes= new ArrayList();
		for (Iterator iter = fChanges.iterator(); iter.hasNext();) {
			final ModeChange change = (ModeChange) iter.next();
			if (change.hasChanged())
				changes.add(change);
		}
		return changes;
	}
	
	public String getComment(Shell shell) {
		return fCommentArea.getCommentWithPrompt(shell);
	}

	private void validatePage() {
		if (fCommentArea.getComment(false).equals("")) { //$NON-NLS-1$
			final IPreferenceStore store = CVSUIPlugin.getPlugin()
					.getPreferenceStore();
			final String allowEmptyComment = store
					.getString(ICVSUIConstants.PREF_ALLOW_EMPTY_COMMIT_COMMENTS);
			if (allowEmptyComment.equals(MessageDialogWithToggle.NEVER)) {
				setPageComplete(false); // then the page is not complete
				return;
			}
		}
		setPageComplete(true);
	}

}
