/*******************************************************************************
 * Copyright (c) 2001, 2004 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.ui.preferences.ui;

import java.io.CharArrayReader;
import java.text.Collator;
import java.util.Dictionary;
import java.util.List;

import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.TextAttribute;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.AccessibleAdapter;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.accessibility.AccessibleControlListener;
import org.eclipse.swt.accessibility.AccessibleEvent;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
import org.eclipse.wst.sse.core.internal.util.Debug;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.ITextRegion;
import org.eclipse.wst.sse.core.text.ITextRegionList;
import org.eclipse.wst.sse.ui.internal.SSEUIMessages;
import org.eclipse.wst.sse.ui.util.EditorUtility;
import org.w3c.dom.Node;

/**
 * This class is configurable by setting 3 properties: 1) an array of Strings
 * as the styleNames; one unique entry for every style type meant to be
 * configurable by the user 2) a Dictionary of descriptions, mapping the
 * styleNames to unique descriptions - meant for use within the selection
 * ComboBox TODO (pa) this should probably be working off document partitions
 * now (2.1+) 3) a Dictionary mapping parsed ITextRegion contexts (strings) to
 * the locally defined styleNames
 *  
 */
public class StyledTextColorPicker extends Composite {
	protected class DescriptionSorter extends org.eclipse.wst.sse.ui.util.Sorter {
		Collator collator = Collator.getInstance();

		public boolean compare(Object elementOne, Object elementTwo) {
			/**
			 * Returns true if elementTwo is 'greater than' elementOne This is
			 * the 'ordering' method of the sort operation. Each subclass
			 * overides this method with the particular implementation of the
			 * 'greater than' concept for the objects being sorted.
			 */
			return (collator.compare(elementOne.toString(), elementTwo.toString())) < 0;
		}
	}

	public static final String BACKGROUND = "background"; //$NON-NLS-1$
	public static final String BOLD = "bold"; //$NON-NLS-1$
	public static final String COLOR = "color"; //$NON-NLS-1$

	// names for preference elements ... non-NLS
	public static final String FOREGROUND = "foreground"; //$NON-NLS-1$
	public static final String ITALIC = "italic"; //$NON-NLS-1$
	public static final String NAME = "name"; //$NON-NLS-1$

	private static final boolean showItalic = false;
	protected AccessibleControlListener backgroundAccListener = new AccessibleControlAdapter() {
		/**
		 * @see org.eclipse.swt.accessibility.AccessibleControlAdapter#getValue(AccessibleControlEvent)
		 */
		public void getValue(AccessibleControlEvent e) {
			if (e.childID == ACC.CHILDID_SELF) {
				e.result = getColorButtonValue(fBackground);
			}
		}
	};
	protected SelectionListener buttonListener = new SelectionListener() {

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

		public void widgetSelected(SelectionEvent e) {
			String namedStyle = getStyleName(fStyleCombo.getItem(fStyleCombo.getSelectionIndex()));
			if (namedStyle == null)
				return;
			if (e.widget == fForeground) {
				// get current (newly old) style
				String prefString = getPreferenceStore().getString(getPreferenceKey(namedStyle));
				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
				if (stylePrefs != null) {
					String oldValue = stylePrefs[0];
					// open color dialog to get new color
					String newValue = changeColor(oldValue);

					if (!newValue.equals(oldValue)) {
						stylePrefs[0] = newValue;
						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
						getPreferenceStore().setValue(getPreferenceKey(namedStyle), newPrefString);
						refresh();
					}
				}
			} else if (e.widget == fBackground) {
				// get current (newly old) style
				String prefString = getPreferenceStore().getString(getPreferenceKey(namedStyle));
				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
				if (stylePrefs != null) {
					String oldValue = stylePrefs[1];
					// open color dialog to get new color
					String newValue = changeColor(oldValue);

					if (!newValue.equals(oldValue)) {
						stylePrefs[1] = newValue;
						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
						getPreferenceStore().setValue(getPreferenceKey(namedStyle), newPrefString);
						refresh();
					}
				}
			} else if (e.widget == fBold) {
				// get current (newly old) style
				String prefString = getPreferenceStore().getString(getPreferenceKey(namedStyle));
				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
				if (stylePrefs != null) {
					String oldValue = stylePrefs[2];
					String newValue = String.valueOf(fBold.getSelection());
					if (!newValue.equals(oldValue)) {
						stylePrefs[2] = newValue;
						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
						getPreferenceStore().setValue(getPreferenceKey(namedStyle), newPrefString);
						refresh();
					}
				}
			} else if (showItalic && e.widget == fItalic) {
				// get current (newly old) style
				String prefString = getPreferenceStore().getString(getPreferenceKey(namedStyle));
				String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
				if (stylePrefs != null) {
					String oldValue = stylePrefs[3];
					String newValue = String.valueOf(fItalic.getSelection());
					if (!newValue.equals(oldValue)) {
						stylePrefs[3] = newValue;
						String newPrefString = ColorHelper.packStylePreferences(stylePrefs);
						getPreferenceStore().setValue(getPreferenceKey(namedStyle), newPrefString);
						refresh();
					}
				}
			} else if (e.widget == fClearStyle) {
				getPreferenceStore().setToDefault(getPreferenceKey(namedStyle));
				refresh();
			}
		}
	};

	protected SelectionListener comboListener = new SelectionListener() {

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

		public void widgetSelected(SelectionEvent e) {
			int selectedIndex = fStyleCombo.getSelectionIndex();
			String description = selectedIndex >= 0 ? fStyleCombo.getItem(selectedIndex) : null;
			activate(getStyleName(description));
		}
	};
	protected Button fBackground;
	protected Label fBackgroundLabel;
	protected Button fBold;
	protected Button fClearStyle;
	// Dictionary mapping the ITextRegion types above to color names, which
	// are, in turn, attributes
	protected Dictionary fContextStyleMap = null;
	protected Color fDefaultBackground = getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);

	protected Color fDefaultForeground = getDisplay().getSystemColor(SWT.COLOR_LIST_FOREGROUND);
	// Dictionary mapping the ITextRegion types above to display strings, for
	// use in the combo box
	protected Dictionary fDescriptions = null;
	protected Button fForeground;
	protected Label fForegroundLabel;
//	private String fGeneratorKey;
	protected String fInput = ""; //$NON-NLS-1$
	protected Button fItalic;

	private IStructuredDocumentRegion fNodes = null;
	// defect 200764 - ACC:display values for color buttons
	protected AccessibleControlListener foregroundAccListener = new AccessibleControlAdapter() {
		/**
		 * @see org.eclipse.swt.accessibility.AccessibleControlAdapter#getValue(AccessibleControlEvent)
		 */
		public void getValue(AccessibleControlEvent e) {
			if (e.childID == ACC.CHILDID_SELF) {
				e.result = getColorButtonValue(fForeground);
			}
		}
	};
	// A RegionParser, which will turn the input into
	// IStructuredDocumentRegion(s) and Regions
	protected RegionParser fParser = null;

	private IPreferenceStore fPreferenceStore;
	protected Combo fStyleCombo = null;
	// The list of supported ITextRegion types [Strings]
	protected List fStyleList = null;

	// controls in picker
	protected StyledText fText = null;

	/**
	 * XMLTextColorPicker constructor comment.
	 * 
	 * @param parent
	 *            org.eclipse.swt.widgets.Composite
	 * @param style
	 *            int
	 */
	public StyledTextColorPicker(Composite parent, int style) {
		super(parent, style);
		//GridLayout
		GridLayout layout = new GridLayout();
		layout.numColumns = 1;
		setLayout(layout);
		createControls(this);
	}

	// activate controls based on the given local color type
	private void activate(String namedStyle) {
		if (namedStyle == null) {
			fForeground.setEnabled(false);
			fBackground.setEnabled(false);
			fClearStyle.setEnabled(false);
			fBold.setEnabled(false);
			if (showItalic)
				fItalic.setEnabled(false);
			fForegroundLabel.setEnabled(false);
			fBackgroundLabel.setEnabled(false);
		} else {
			fForeground.setEnabled(true);
			fBackground.setEnabled(true);
			fClearStyle.setEnabled(true);
			fBold.setEnabled(true);
			if (showItalic)
				fItalic.setEnabled(true);
			fForegroundLabel.setEnabled(true);
			fBackgroundLabel.setEnabled(true);
		}
		TextAttribute attribute = getAttribute(namedStyle);
		Color color = attribute.getForeground();
		if (color == null) {
			color = fDefaultForeground;
		}
		if (fForeground.getSize().x > 0 && fForeground.getSize().y > 0 && (fForeground.getImage() == null || fForeground.getImage().getImageData() == null || fForeground.getImage().getImageData().getRGBs() == null || fForeground.getImage().getImageData().getRGBs().length < 1 || !fForeground.getImage().getImageData().getRGBs()[0].equals(color.getRGB()))) {
			if (fForeground.getImage() != null)
				fForeground.getImage().dispose();
			Image foreground = new Image(getDisplay(), new ImageData(fForeground.getSize().x, fForeground.getSize().y, 1, new PaletteData(new RGB[]{color.getRGB()})));
			fForeground.setImage(foreground);
		}
		color = attribute.getBackground();
		if (color == null) {
			color = fDefaultBackground;
		}
		if (fBackground.getSize().x > 0 && fBackground.getSize().y > 0 && (fBackground.getImage() == null || fBackground.getImage().getImageData() == null || fBackground.getImage().getImageData().getRGBs() == null || fBackground.getImage().getImageData().getRGBs().length < 1 || !fBackground.getImage().getImageData().getRGBs()[0].equals(color.getRGB()))) {
			if (fBackground.getImage() != null)
				fBackground.getImage().dispose();
			Image background = new Image(getDisplay(), new ImageData(fBackground.getSize().x, fBackground.getSize().y, 1, new PaletteData(new RGB[]{color.getRGB()})));
			fBackground.setImage(background);
		}
		fBold.setSelection((attribute.getStyle() & SWT.BOLD) != 0);
		if (showItalic)
			fItalic.setSelection((attribute.getStyle() & SWT.ITALIC) != 0);
	}

	protected void applyStyles() {
		if (fText == null || fText.isDisposed() || fInput == null || fInput.length() == 0)
			return;
		//		List regions = fParser.getRegions();
		IStructuredDocumentRegion node = fNodes;
		while (node != null) {
			ITextRegionList regions = node.getRegions();
			for (int i = 0; i < regions.size(); i++) {
				ITextRegion currentRegion = regions.get(i);
				// lookup the local coloring type and apply it
				String namedStyle = (String) getContextStyleMap().get(currentRegion.getType());
				if (namedStyle == null)
					continue;
				TextAttribute attribute = getAttribute(namedStyle);
				if (attribute == null)
					continue;
				StyleRange style = new StyleRange(node.getStartOffset(currentRegion), currentRegion.getLength(), attribute.getForeground(), attribute.getBackground(), attribute.getStyle());
				fText.setStyleRange(style);
			}
			node = node.getNext();
		}
	}

	private RGB changeColor(RGB startValue) {
		ColorDialog colorDlg = new ColorDialog(getShell());
		if (startValue != null)
			colorDlg.setRGB(startValue);
		colorDlg.open();
		RGB newRGB = colorDlg.getRGB();
		if (newRGB != null)
			return newRGB;
		return startValue;
	}

	private String changeColor(String rgb) {
		String changedColor = "null"; //$NON-NLS-1$

		RGB newColor = changeColor(ColorHelper.toRGB(rgb));
		// null check to see if using default value
		if (newColor != null)
			changedColor = ColorHelper.toRGBString(newColor);
		return changedColor;
	}

	protected void close() {
	}

	/**
	 * Determines size of color button copied from
	 * org.eclipse.jdt.internal.ui.preferences.ColorEditor 1 modification -
	 * added 4 to final height
	 */
	private Point computeImageSize(Control window) {
		GC gc = new GC(window);
		Font f = JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT);
		gc.setFont(f);
		int height = gc.getFontMetrics().getHeight();
		gc.dispose();
		Point p = new Point(height * 3 - 6, height + 4);
		return p;
	}

	/**
	 * Creates an new checkbox instance and sets the default layout data.
	 * 
	 * @param group
	 *            the composite in which to create the checkbox
	 * @param label
	 *            the string to set into the checkbox
	 * @return the new checkbox
	 */
	private Button createCheckBox(Composite group, String label) {
		Button button = new Button(group, SWT.CHECK | SWT.CENTER);
		if (label != null)
			button.setText(label);
		GridData data = new GridData(GridData.FILL_BOTH);
		data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_END;
		//	data.verticalAlignment = GridData.VERTICAL_ALIGN_FILL;
		button.setLayoutData(data);
		return button;
	}

	private Combo createCombo(Composite parent, String[] labels, int selectedItem) {
		Combo combo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
		combo.setItems(labels);
		if (selectedItem >= 0)
			combo.select(selectedItem);
		GridData data = new GridData(GridData.FILL_HORIZONTAL);
		data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_FILL;
		combo.setLayoutData(data);
		return combo;
	}

	/**
	 * Creates composite control and sets the default layout data.
	 */
	private Composite createComposite(Composite parent, int numColumns) {
		Composite composite = new Composite(parent, SWT.NULL);
		//GridLayout
		GridLayout layout = new GridLayout();
		layout.numColumns = numColumns;
		layout.horizontalSpacing = 5;
		layout.makeColumnsEqualWidth = false;
		composite.setLayout(layout);
		//GridData
		GridData data = new GridData(GridData.FILL_VERTICAL);
		data.grabExcessVerticalSpace = false;
		data.verticalAlignment = GridData.VERTICAL_ALIGN_CENTER;
		composite.setLayoutData(data);
		return composite;
	}

	protected void createControls(Composite parent) {
		Composite styleRow = createComposite(parent, 3);
		// row 1 - content type label, combo box, restore defaults
		createLabel(styleRow, SSEUIMessages.Content_type__UI_); //$NON-NLS-1$ = "Content type:"
		// Contexts combo box
		fStyleCombo = createCombo(styleRow, new String[0], -1);
		fClearStyle = createPushButton(styleRow, SSEUIMessages.Restore_Default_UI_); //$NON-NLS-1$ = "Restore Default"
		Composite styleRow2;
		if (showItalic)
			styleRow2 = createComposite(parent, 7);
		else
			styleRow2 = createComposite(parent, 6);
		// row 2 - foreground label, button, background label, button, bold,
		// italics?
		fForegroundLabel = createLabel(styleRow2, SSEUIMessages.Foreground_UI_); //$NON-NLS-1$ = "Foreground"
		fForeground = createPushButton(styleRow2, ""); //$NON-NLS-1$
		setAccessible(fForeground, fForegroundLabel.getText());
		fForeground.getAccessible().addAccessibleControlListener(foregroundAccListener); // defect
		// 200764
		// -
		// ACC:display
		// values
		// for
		// color
		// buttons
		Point buttonSize = computeImageSize(parent);
		((GridData) fForeground.getLayoutData()).widthHint = buttonSize.x;
		((GridData) fForeground.getLayoutData()).heightHint = buttonSize.y;
		fBackgroundLabel = createLabel(styleRow2, SSEUIMessages.Background_UI_); //$NON-NLS-1$ = "Background"
		fBackground = createPushButton(styleRow2, ""); //$NON-NLS-1$
		setAccessible(fBackground, fBackgroundLabel.getText());
		fBackground.getAccessible().addAccessibleControlListener(backgroundAccListener); // defect
		// 200764
		// -
		// ACC:display
		// values
		// for
		// color
		// buttons
		((GridData) fBackground.getLayoutData()).widthHint = buttonSize.x;
		((GridData) fBackground.getLayoutData()).heightHint = buttonSize.y;
		createLabel(styleRow2, ""); //$NON-NLS-1$
		fBold = createCheckBox(styleRow2, SSEUIMessages.Bold_UI_);
		if (showItalic)
			fItalic = createCheckBox(styleRow2, SSEUIMessages.Italics_UI);
		//		// Defaults checkbox
		fForeground.setEnabled(false);
		fBackground.setEnabled(false);
		fClearStyle.setEnabled(false);
		fBold.setEnabled(false);
		if (showItalic)
			fItalic.setEnabled(false);
		fForegroundLabel.setEnabled(false);
		fBackgroundLabel.setEnabled(false);
		Composite sample = createComposite(parent, 1);
		createLabel(sample, SSEUIMessages.Sample_text__UI_); //$NON-NLS-1$ = "&Sample text:"
		fText = new StyledText(sample, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.READ_ONLY);
		GridData data = new GridData(GridData.FILL_BOTH);
		fText.setLayoutData(data);
		fText.setEditable(false);
		fText.setBackground(fDefaultBackground);
		fText.setFont(JFaceResources.getTextFont());
		fText.addKeyListener(getTextKeyListener());
		fText.addSelectionListener(getTextSelectionListener());
		fText.addMouseListener(getTextMouseListener());
		fText.addTraverseListener(getTraverseListener()); // defect 220377 -
		// Provide tab
		// traversal for
		// fText widget
		setAccessible(fText, SSEUIMessages.Sample_text__UI_); //$NON-NLS-1$ = "&Sample text:"
		fForeground.addSelectionListener(buttonListener);
		fBackground.addSelectionListener(buttonListener);
		fClearStyle.addSelectionListener(buttonListener);
		fBold.addSelectionListener(buttonListener);
		if (showItalic)
			fItalic.addSelectionListener(buttonListener);
		fStyleCombo.addSelectionListener(comboListener);
	}

	/**
	 * Utility method that creates a label instance and sets the default
	 * layout data.
	 */
	private Label createLabel(Composite parent, String text) {
		Label label = new Label(parent, SWT.LEFT);
		label.setText(text);
		GridData data = new GridData();
		data.horizontalAlignment = GridData.FILL;
		label.setLayoutData(data);
		return label;
	}

	private Button createPushButton(Composite parent, String label) {
		Button button = new Button(parent, SWT.PUSH);
		button.setText(label);
		GridData data = new GridData(GridData.FILL_BOTH);
		//	data.horizontalAlignment = GridData.FILL;
		button.setLayoutData(data);
		return button;
	}

	protected TextAttribute getAttribute(String namedStyle) {
		TextAttribute ta = new TextAttribute(getDefaultForeground(), getDefaultBackground(), SWT.NORMAL);

		if (namedStyle != null && getPreferenceStore() != null) {
			String prefString = getPreferenceStore().getString(getPreferenceKey(namedStyle));
			String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString);
			if (stylePrefs != null) {
				RGB foreground = ColorHelper.toRGB(stylePrefs[0]);
				RGB background = ColorHelper.toRGB(stylePrefs[1]);

				int fontModifier = SWT.NORMAL;
				boolean bold = Boolean.valueOf(stylePrefs[2]).booleanValue();
				if (bold)
					fontModifier = fontModifier | SWT.BOLD;

				if (showItalic) {
					boolean italic = Boolean.valueOf(stylePrefs[3]).booleanValue();
					if (italic)
						fontModifier = fontModifier | SWT.ITALIC;
				}

				ta = new TextAttribute((foreground != null) ? EditorUtility.getColor(foreground) : null, (background != null) ? EditorUtility.getColor(background) : null, fontModifier);
			}
		}
		return ta;
	}

	// defect 200764 - ACC:display values for color buttons
	/**
	 * @return String - color Button b's current RBG value
	 */
	private String getColorButtonValue(Button b) {
		if ((b == null) || (b.getImage() == null) || (b.getImage().getImageData() == null) || (b.getImage().getImageData().getRGBs() == null) || (b.getImage().getImageData().getRGBs()[0] == null))
			return null;
		String val = b.getImage().getImageData().getRGBs()[0].toString();
		return val;
	}

	/**
	 * @deprecated use getPreferenceStore instead left for legacy clients,
	 *             delete by WTP M4
	 */
	public Node getColorsNode() {
		//return fColorsNode;
		return null;
	}

	/**
	 * @return java.util.Dictionary
	 */
	public Dictionary getContextStyleMap() {
		return fContextStyleMap;
	}

	/**
	 * @return org.eclipse.swt.graphics.Color
	 */
	public Color getDefaultBackground() {
		return fDefaultBackground;
	}

	/**
	 * @return org.eclipse.swt.graphics.Color
	 */
	public Color getDefaultForeground() {
		return fDefaultForeground;
	}

	/**
	 * @return java.util.Dictionary
	 */
	public Dictionary getDescriptions() {
		return fDescriptions;
	}

	public Font getFont() {
		return fText.getFont();
	}

	protected String getNamedStyleAtOffset(int offset) {
		// ensure the offset is clean
		if (offset >= fInput.length())
			return getNamedStyleAtOffset(fInput.length() - 1);
		else if (offset < 0)
			return getNamedStyleAtOffset(0);
		// find the ITextRegion at this offset
		if (fNodes == null)
			return null;
		IStructuredDocumentRegion aNode = fNodes;
		while (aNode != null && !aNode.containsOffset(offset))
			aNode = aNode.getNext();
		if (aNode != null) {
			// find the ITextRegion's Context at this offset
			ITextRegion interest = aNode.getRegionAtCharacterOffset(offset);
			if (interest == null)
				return null;
			if (offset > aNode.getTextEndOffset(interest))
				return null;
			String regionContext = interest.getType();
			if (regionContext == null)
				return null;
			// find the named style (internal/selectable name) for that
			// context
			String namedStyle = (String) getContextStyleMap().get(regionContext);
			if (namedStyle != null) {
				return namedStyle;
			}
		}
		return null;
	}

	/**
	 * @return com.ibm.sed.parser.RegionParser
	 */
	public RegionParser getParser() {
		return fParser;
	}

	/**
	 * @deprecated just key key (no need for generator)
	 */
	private String getPreferenceKey(String key) {
		String newKey = key;
//		if (fGeneratorKey != null) {
//			newKey = PreferenceKeyGenerator.generateKey(key, fGeneratorKey);
//		}
		return newKey;
	}

	private IPreferenceStore getPreferenceStore() {
		return fPreferenceStore;
	}

	/**
	 * @return String[]
	 */
	public List getStyleList() {
		return fStyleList;
	}

	private String getStyleName(String description) {
		if (description == null)
			return null;
		String styleName = null;
		java.util.Enumeration keys = getDescriptions().keys();
		while (keys.hasMoreElements()) {
			String test = keys.nextElement().toString();
			if (getDescriptions().get(test).equals(description)) {
				styleName = test;
				break;
			}
		}
		return styleName;
	}

	public String getText() {
		return fInput;
	}

	private KeyListener getTextKeyListener() {
		return new KeyListener() {
			public void keyPressed(KeyEvent e) {
				if (e.widget instanceof StyledText) {
					int x = ((StyledText) e.widget).getCaretOffset();
					selectColorAtOffset(x);
				}
			}

			public void keyReleased(KeyEvent e) {
				if (e.widget instanceof StyledText) {
					int x = ((StyledText) e.widget).getCaretOffset();
					selectColorAtOffset(x);
				}
			}
		};
	}

	private MouseListener getTextMouseListener() {
		return new MouseListener() {
			public void mouseDoubleClick(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
			}

			public void mouseUp(MouseEvent e) {
				if (e.widget instanceof StyledText) {
					int x = ((StyledText) e.widget).getCaretOffset();
					selectColorAtOffset(x);
				}
			}
		};
	}

	private SelectionListener getTextSelectionListener() {
		return new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
				selectColorAtOffset(e.x);
				if (e.widget instanceof StyledText) {
					((StyledText) e.widget).setSelection(e.x);
				}
			}

			public void widgetDoubleSelected(SelectionEvent e) {
				selectColorAtOffset(e.x);
				if (e.widget instanceof StyledText) {
					((StyledText) e.widget).setSelection(e.x);
				}
			}

			public void widgetSelected(SelectionEvent e) {
				selectColorAtOffset(e.x);
				if (e.widget instanceof StyledText) {
					((StyledText) e.widget).setSelection(e.x);
				}
			}
		};
	}

	// defect 220377 - Provide tab traversal for fText widget
	private TraverseListener getTraverseListener() {
		return new TraverseListener() {
			/**
			 * @see org.eclipse.swt.events.TraverseListener#keyTraversed(TraverseEvent)
			 */
			public void keyTraversed(TraverseEvent e) {
				if (e.widget instanceof StyledText) {
					if ((e.detail == SWT.TRAVERSE_TAB_NEXT) || (e.detail == SWT.TRAVERSE_TAB_PREVIOUS))
						e.doit = true;
				}
			}
		};
	}

	// refresh the GUI after a color change
	public void refresh() {
		fText.setRedraw(false);
		int selectedIndex = fStyleCombo.getSelectionIndex();
		String description = selectedIndex >= 0 ? fStyleCombo.getItem(selectedIndex) : null;
		activate(getStyleName(description));
		// update Font
		fText.setFont(JFaceResources.getTextFont());
		// reapplyStyles
		applyStyles();
		fText.setRedraw(true);
	}

	public void releasePickerResources() {
		if (fForeground != null && !fForeground.isDisposed() && fForeground.getImage() != null)
			fForeground.getImage().dispose();
		if (fBackground != null && !fBackground.isDisposed() && fBackground.getImage() != null)
			fBackground.getImage().dispose();
	}

	private void selectColorAtOffset(int offset) {
		String namedStyle = getNamedStyleAtOffset(offset);
		if (namedStyle == null) {
			fStyleCombo.deselectAll();
			activate(null);
			return;
		}
		String description = (String) getDescriptions().get(namedStyle);
		if (description == null)
			return;
		int itemCount = fStyleCombo.getItemCount();
		for (int i = 0; i < itemCount; i++) {
			if (fStyleCombo.getItem(i).equals(description)) {
				fStyleCombo.select(i);
				break;
			}
		}
		activate(namedStyle);
	}

	/**
	 * Specifically set the reporting name of a control for accessibility
	 */
	private void setAccessible(Control control, String name) {
		if (control == null)
			return;
		final String n = name;
		control.getAccessible().addAccessibleListener(new AccessibleAdapter() {
			public void getName(AccessibleEvent e) {
				if (e.childID == ACC.CHILDID_SELF)
					e.result = n;
			}
		});
	}

	/**
	 * @deprecated use setPreferenceStore instead left for legacy clients,
	 *             delete by WTP M4
	 */
	public void setColorsNode(Node newColorsNode) {
		//fColorsNode = newColorsNode;
	}

	/**
	 * @param newContextStyleMap
	 *            java.util.Dictionary
	 */
	public void setContextStyleMap(Dictionary newContextStyleMap) {
		fContextStyleMap = newContextStyleMap;
	}

	/**
	 * @param newDefaultBackground
	 *            org.eclipse.swt.graphics.Color
	 */
	public void setDefaultBackground(Color newDefaultBackground) {
		fDefaultBackground = newDefaultBackground;
	}

	/**
	 * @deprecated use setPreferenceStore instead left for legacy clients,
	 *             delete by WTP M4
	 */
	public void setDefaultColorsNode(Node newDefaultColorsNode) {
		//fDefaultColorsNode = newDefaultColorsNode;
	}

	/**
	 * @param newDefaultForeground
	 *            org.eclipse.swt.graphics.Color
	 */
	public void setDefaultForeground(Color newDefaultForeground) {
		fDefaultForeground = newDefaultForeground;
	}

	/**
	 * @param newDescriptions
	 *            java.util.Dictionary
	 */
	public void setDescriptions(Dictionary newDescriptions) {
		fDescriptions = newDescriptions;
		updateStyleList();
	}

	public void setFont(Font font) {
		fText.setFont(font);
		fText.redraw();
	}

	/**
	 * @deprecated generator key should no longer be needed
	 */
	public void setGeneratorKey(String key) {
//		fGeneratorKey = key;
	}

	/**
	 * @param newParser
	 *            com.ibm.sed.parser.RegionParser
	 */
	public void setParser(RegionParser newParser) {
		fParser = newParser;
	}

	public void setPreferenceStore(IPreferenceStore store) {
		fPreferenceStore = store;
	}

	/**
	 * @param newStyleList
	 *            String[]
	 */
	public void setStyleList(List newStyleList) {
		fStyleList = newStyleList;
		updateStyleList();
	}

	public void setText(String s) {
		fInput = s;
		getParser().reset(new CharArrayReader(fInput.toCharArray()));
		fNodes = getParser().getDocumentRegions();
		if (Debug.displayInfo)
			System.out.println("Length of input: " //$NON-NLS-1$
						//$NON-NLS-1$
						+ s.length() + ", " //$NON-NLS-1$
						+ getParser().getRegions().size() + " regions."); //$NON-NLS-1$
		if (fText != null)
			fText.setText(s);
		applyStyles();
	}



	/**
	 * @return org.eclipse.swt.graphics.RGB
	 * @param anRGBString
	 *            java.lang.String
	 * @param defaultRGB
	 *            org.eclipse.swt.graphics.RGB
	 */
	// TODO: never used
	 RGB toRGB(String anRGBString, RGB defaultRGB) {
		RGB result = ColorHelper.toRGB(anRGBString);
		if (result == null)
			return defaultRGB;
		return result;
	}

	private void updateStyleList() {
		if (fStyleList == null || fDescriptions == null)
			return;
		String[] descriptions = new String[fStyleList.size()];
		for (int i = 0; i < fStyleList.size(); i++) {
			if (fStyleList.get(i) != null)
				descriptions[i] = (String) getDescriptions().get(fStyleList.get(i));
			else
				descriptions[i] = (String) fStyleList.get(i);
		}
		Object[] sortedObjects = new DescriptionSorter().sort(descriptions);
		String[] sortedDescriptions = new String[descriptions.length];
		for (int i = 0; i < descriptions.length; i++) {
			sortedDescriptions[i] = sortedObjects[i].toString();
		}
		fStyleCombo.setItems(sortedDescriptions);
		fStyleCombo.select(0); //defect 219855 - initially select first item
		// in comboBox
		//		fStyleCombo.deselectAll();
	}



}
