/*******************************************************************************
 * 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
 *******************************************************************************/
// Based on version 1.12 of original xsdeditor
package org.eclipse.wst.xsd.ui.internal.wizards;

import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorContextIds;
import org.eclipse.wst.xsd.ui.internal.editor.XSDEditorPlugin;
import org.eclipse.wst.xsd.ui.internal.util.ViewUtility;
import org.eclipse.xsd.XSDPatternFacet;



/*
-other regex features (eg case sensitivity, ^ or $, |, etc etc)
-smarter model
-better keyboard navigation
-update list of tokens 
*/

public class RegexCompositionPage extends WizardPage
{
  private static final boolean debug = false;

  /* The text representation of our pattern. */
  private StyledText value; 

  /* The StyleRange used to color code the current parse error. */
  private StyleRange currentError;

  /* The regex terms we can form tokens from. */
  private Combo terms;

  /* The checkbox for activating auto-escape mode. */  
  private Button escapeCheckbox;
  
  /* On/off status of auto-escape mode. */ 
  private boolean autoEscapeStatus;

  /* The Add Token button. */
  private Button add;


  // The following controls are used in the occurrence selection group

  private Text repeatValue;

  private Text rangeMinValue;
  private Text rangeMaxValue;
  private Label rangeToLabel;  

  private Button singleRadio;
  private Button starRadio;
  private Button plusRadio;
  private Button optionalRadio; 
  private Button repeatRadio;
  private Button rangeRadio;

  
  // The following variables used as part of the model. 

  /* Our pattern. */
  private XSDPatternFacet pattern;

  /* Model used to store the current token. */
  private RegexNode node;    

  /* The flags passed to the new RegularExpression object.  Default value includes:
      X = XMLSchema mode    */
  private String regexFlags = "X";
      

  /* Is the current regex token valid? */
  private boolean isValidToken;

  /* The label used to indicate the value's caret position when it looses focus. */
  private Label caretLabel;

  /* The pixel offsets needed to align the label icon with the caret location.
     These are dependent on the icon used. */
  private static final int CARET_LABEL_X_OFFSET = -3;
  private static final int CARET_LABEL_Y_OFFSET = 19;

  
  /* Enumerated constants for specifying the type of an error message. */
  private static final int TOKEN = 0;
  private static final int SELECTION = 1;
  private static final int PARSE = 2;
  
  private static final int NUM_ERROR_MESSAGE_TYPES = 3;
  
  /* The current error message for each type of error.  A value of null indicates no message. 
     The array is indexed according to the above constants.
  */
  private String[] currentErrorMessages;


  public RegexCompositionPage(XSDPatternFacet pattern)
  {
    super(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_COMPOSITION_PAGE_TITLE"));
    this.pattern = pattern;

    setTitle(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_COMPOSITION_PAGE_TITLE"));
    setDescription(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_COMPOSITION_PAGE_DESCRIPTION"));
  }

  public void createControl(Composite parent)
  {
    // Set up our model and validator
    node = new RegexNode();
        
    isValidToken = true;

    currentErrorMessages = new String[NUM_ERROR_MESSAGE_TYPES];

    // The main composite
    Composite composite= new Composite(parent, SWT.NONE);
    WorkbenchHelp.setHelp(composite, XSDEditorContextIds.XSDR_COMPOSITION_PAGE);
    composite.setLayout(new GridLayout());


    // The composite for the token combo box, label, and auto-escape checkbox
    Composite tokenComposite = new Composite (composite, SWT.NONE);
    GridLayout tokenCompositeLayout = new GridLayout();
    tokenCompositeLayout.numColumns = 3;
    tokenCompositeLayout.marginWidth = 0;
    tokenComposite.setLayout(tokenCompositeLayout);


    new Label(tokenComposite, SWT.LEFT).setText(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_TOKEN_LABEL"));
    
    terms = new Combo(tokenComposite, SWT.DROP_DOWN);
    WorkbenchHelp.setHelp(terms, XSDEditorContextIds.XSDR_COMPOSITION_TOKEN);
    for (int i = 0; i < RegexNode.getNumRegexTerms(); i++)
    {
      terms.add(RegexNode.getRegexTermText(i));
    }
    terms.addListener(SWT.Modify, new ComboListener());
    terms.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_TERMS"));

    escapeCheckbox = new Button(tokenComposite, SWT.CHECK);
    escapeCheckbox.setText(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_AUTO_ESCAPE_CHECKBOX_LABEL"));
    escapeCheckbox.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_AUTO_ESCAPE_CHECKBOX")); 
    escapeCheckbox.addSelectionListener(new CheckboxListener());
    autoEscapeStatus = false;
    
    tokenComposite.pack();


    // Set up the composites pertaining to the selection of occurrence quantifiers

    Group occurrenceSelectionArea = new Group(composite, SWT.NONE);
    occurrenceSelectionArea.setText(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_OCCURENCE_LABEL"));
    WorkbenchHelp.setHelp(occurrenceSelectionArea, XSDEditorContextIds.XSDR_COMPOSITION_OCCURRENCE_GROUP);
    GridLayout selectionAreaLayout = new GridLayout();
    selectionAreaLayout.numColumns = 2;
    occurrenceSelectionArea.setLayout(selectionAreaLayout);

    // Listener used for all of the text fields
    TextListener textListener = new TextListener();
    

    // Add the radio buttons
    RadioSelectListener radioSelectListener = new RadioSelectListener();

    singleRadio = addOccurenceRadioButton(RegexNode.SINGLE, occurrenceSelectionArea, radioSelectListener);
    WorkbenchHelp.setHelp(singleRadio, XSDEditorContextIds.XSDR_COMPOSITION_JUST_ONCE);
    ViewUtility.createHorizontalFiller(occurrenceSelectionArea, 1);

    starRadio = addOccurenceRadioButton(RegexNode.STAR, occurrenceSelectionArea, radioSelectListener);
    WorkbenchHelp.setHelp(starRadio, XSDEditorContextIds.XSDR_COMPOSITION_ZERO_OR_MORE);
    ViewUtility.createHorizontalFiller(occurrenceSelectionArea, 1);

    plusRadio = addOccurenceRadioButton(RegexNode.PLUS, occurrenceSelectionArea, radioSelectListener);
    WorkbenchHelp.setHelp(plusRadio, XSDEditorContextIds.XSDR_COMPOSITION_ONE_OR_MORE);
    ViewUtility.createHorizontalFiller(occurrenceSelectionArea, 1);

    optionalRadio = addOccurenceRadioButton(RegexNode.OPTIONAL, occurrenceSelectionArea, radioSelectListener);
    WorkbenchHelp.setHelp(optionalRadio, XSDEditorContextIds.XSDR_COMPOSITION_OPTIONAL);
    ViewUtility.createHorizontalFiller(occurrenceSelectionArea, 1);

    repeatRadio = addOccurenceRadioButton(RegexNode.REPEAT, occurrenceSelectionArea, radioSelectListener);
    WorkbenchHelp.setHelp(repeatRadio, XSDEditorContextIds.XSDR_COMPOSITION_REPEAT);

    // Add text field for specifying number of repeats
    Composite repeatWidgets = new Composite(occurrenceSelectionArea, SWT.NONE);
    RowLayout repeatWidgetsLayout = new RowLayout();
    repeatWidgetsLayout.marginTop = 0;
    repeatWidgetsLayout.marginBottom = 0;
    repeatWidgetsLayout.marginLeft = 0;
    repeatWidgetsLayout.marginRight = 0;
    repeatWidgets.setLayout(repeatWidgetsLayout);        
    
    repeatValue = new Text(repeatWidgets, SWT.SINGLE | SWT.BORDER);
    repeatValue.addListener(SWT.Modify, textListener);
    WorkbenchHelp.setHelp(repeatValue, XSDEditorContextIds.XSDR_COMPOSITION_REPEAT_TEXT);
    repeatValue.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_REPEAT"));
    setEnabledStatus(RegexNode.REPEAT, false);
    
    repeatWidgets.pack();
    
    rangeRadio = addOccurenceRadioButton(RegexNode.RANGE, occurrenceSelectionArea, radioSelectListener);
    WorkbenchHelp.setHelp(rangeRadio, XSDEditorContextIds.XSDR_COMPOSITION_RANGE);

    // Add text fields and labels for specifying the range    
    Composite rangeWidgets = new Composite(occurrenceSelectionArea, SWT.NONE);
    RowLayout rangeWidgetsLayout = new RowLayout();
    rangeWidgetsLayout.marginTop = 0;
    rangeWidgetsLayout.marginBottom = 0;
    rangeWidgetsLayout.marginLeft = 0;
    rangeWidgetsLayout.marginRight = 0;
    rangeWidgets.setLayout(rangeWidgetsLayout);
    
    rangeMinValue = new Text(rangeWidgets, SWT.SINGLE | SWT.BORDER);
    rangeMinValue.addListener(SWT.Modify, textListener);
    WorkbenchHelp.setHelp(rangeMinValue, XSDEditorContextIds.XSDR_COMPOSITION_RANGE_MIN);
    rangeMinValue.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_MIN"));
    
    rangeToLabel = new Label(rangeWidgets, SWT.NONE);
    rangeToLabel.setText(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_TO_LABEL"));
    
    rangeMaxValue = new Text(rangeWidgets, SWT.SINGLE | SWT.BORDER);
    rangeMaxValue.addListener(SWT.Modify, textListener);
    rangeMaxValue.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_MAX"));
    WorkbenchHelp.setHelp(rangeMaxValue, XSDEditorContextIds.XSDR_COMPOSITION_RANGE_MAX);

    setEnabledStatus(RegexNode.RANGE, false);
    rangeWidgets.pack();
    
    singleRadio.setSelection(true);
    
    occurrenceSelectionArea.pack();

    // The add button
    add = new Button(composite, SWT.PUSH);
    add.addSelectionListener(new ButtonSelectListener());
    add.setText(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_ADD_BUTTON_LABEL"));
    WorkbenchHelp.setHelp(add, XSDEditorContextIds.XSDR_COMPOSITION_ADD);
    add.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_ADD_BUTTON"));

    
    Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
    separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

    
    // Our main text box

    Label valueLabel= new Label(composite, SWT.LEFT);
    valueLabel.setText(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_CURRENT_REGEX_LABEL"));
    
    value = new StyledText(composite, SWT.SINGLE | SWT.BORDER);
    value.addListener(SWT.Modify, textListener);
    value.addListener(SWT.Selection, textListener);
    WorkbenchHelp.setHelp(value, XSDEditorContextIds.XSDR_COMPOSITION_CURRENT);
    value.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_CURRENT_REGEX"));
    value.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

    value.setFocus();

    // StyleRange used for highlighting parse errors
    currentError = new StyleRange();
    currentError.length = 1;
    currentError.foreground = parent.getDisplay().getSystemColor(SWT.COLOR_RED);

    // The caret label
    caretLabel = new Label(composite, SWT.LEFT);
    caretLabel.setImage(XSDEditorPlugin.getXSDImage("icons/RegexWizardArrow.gif"));
    caretLabel.setToolTipText(XSDEditorPlugin.getXSDString("_UI_TOOLTIP_REGEX_WIZARD_CARET_LABEL"));
    setShowCaretLabel(true);

    value.addFocusListener(new TextFocusListener());

    terms.select(0);


    setControl(composite);
  }


  public void setVisible(boolean visible)
  {
    super.setVisible(visible);

    value.setText(pattern.getLexicalValue());
    value.setCaretOffset(value.getCharCount());
  }

  public void dispose()
  {
    super.dispose();
  }


  /**
   * Sets the visible status of caretLabel to status.  If status is true, then we also update the position
   * of caretLabel in one of two ways.  If there is no active selection in value, we set caretLabel's
   * position to correspond with the position of the actual caret.  Alternatively, if there is an active selection
   * in value, we set caretLabel's position to the beginning of the selection.
   *
   * @param The new visibility status of caretLabel.
   */
  private void setShowCaretLabel(boolean status)
  {
    if (status)
    {
  
      int offset;
      
      if (value.getSelectionText().equals(""))
      {
        offset = value.getCaretOffset();
      }
      else
      {
        offset = value.getSelection().x;
      }
  
      Point p = value.getLocationAtOffset(offset);
      
      p.x += value.getLocation().x;
      p.y = value.getLocation().y;
      
      // Place the label under value, and make sure it is aligned with the caret.
      // The offsets are dependent on the icon used.
      p.x += CARET_LABEL_X_OFFSET;
      p.y += CARET_LABEL_Y_OFFSET;
  
      if (debug)
      {
        System.out.println("POINT: " + p); //$NON-NLS-1$
      }
      
      caretLabel.setLocation(p);
      caretLabel.setVisible(true);
    }
    else
    {
      caretLabel.setVisible(false);
    }
  }


  /**
   * Adds a new radio button to Composite c with SelectionListener l.  The text of the button is the String associated with
   * quantifier.
   *
   * @param quantifier The desired quantifier, as enumerated in RegexNode.
   * @param c The Composite to add the buttons to (normally occurrenceRadioButtons).
   * @param l The SelectionListener (normally radioSelectionListener).
   * @return The newly created button.
   */
  private Button addOccurenceRadioButton(int quantifier, Composite c, SelectionListener l)
  {
    Button result = new Button(c, SWT.RADIO);
    result.setText(RegexNode.getQuantifierText(quantifier));
    result.addSelectionListener(l);
    return result;
  }


  /**
   * Validates the regex in value.  If the regex is valid, clears the Wizard's error message.  If it's not valid,
   *  sets the Wizard's error message accordingly.
   *
   * @return Whether the regex is valid.
   */
  private boolean validateRegex()
  {

    boolean isValid;
    try
    {
      // We validate the regex by checking whether we get a ParseException.
      // By default, we assume that it's valid unless we determine otherwise.
      isValid = true;
      displayRegexErrorMessage(null);
      value.setStyleRange(null);

      Pattern.compile(value.getText());
    }
    catch (PatternSyntaxException pe)
    {
      isValid = false;
      displayRegexErrorMessage(pe.getMessage());

      // An off-by-one bug in the xerces regex parser will sometimes return a location for the parseError that
      //  is off the end of the string.  If this is the case, then we want to highlight the last character.
      if (pe.getIndex() >= value.getText().length())
      {
        currentError.start = value.getText().length() - 1;
      }
      else
      {
        currentError.start = pe.getIndex();
      }

      if (debug)
      {
        System.out.println("Parse Error location: " + pe.getIndex());  //$NON-NLS-1$
        System.out.println("currentError.start: " + currentError.start); //$NON-NLS-1$
      }

      value.setStyleRange(currentError);

    }

    // Another bug in the xerces parser will sometimes throw a RuntimeException instead of a ParseException.
    //  When we get a RuntimeException, we aren't provided with the additional information we need to highlight
    //  the parse error.  So, we merely report that there is an error.
    catch (RuntimeException re)
    {
      displayRegexErrorMessage("");
      value.setStyleRange(null);
      isValid = false;
    }
    
    setPageComplete(isValid);    
    return isValid;
  }

  
  /**
   * Manages the display of error messages.
   * Sets the error message for type to errorMessage.  If errorMessage != null, then we set the Wizard's error message
   * to errorMessage.  If errorMessage == null, then we check whether we have a pending message of another type.
   * If we do, then it is displayed as the Wizard's error message.  If we don't, then the Wizard's error message field
   * is cleared.
   *
   * @param errorMessage The text of the new error message.  A value of null indicates that the error message should
   *  be cleared.
   * @param type The error type, one of PARSE, TOKEN, or SELECTION.
   */ 
  private void displayErrorMessage(String errorMessage, int type)
  {
    String messageToDisplay = null;


    currentErrorMessages[type] = errorMessage;

    messageToDisplay = errorMessage;

    for (int i = 0; i < NUM_ERROR_MESSAGE_TYPES; i++)
    {
      if (messageToDisplay != null)
      {
        break;
      }
      messageToDisplay = currentErrorMessages[i];
    }

    setErrorMessage(messageToDisplay);
  }


  /**
   * Sets the Wizard's error message to message, preceded by a standard prefix.
   *
   * @param message The new error message (or null to clear it).
   */
  private void displayRegexErrorMessage (String errorMessage)
  {
    if (errorMessage == null)
    {
      displayErrorMessage(null, PARSE);
    }
    else
    {
    	if (errorMessage.trim().equals("")) // when there is no error message available.
    	{
        displayErrorMessage(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_REGEX_ERROR"),
                           PARSE);
      }
      else
      {
        displayErrorMessage(errorMessage, PARSE);
      }
    }
  }


  /**
   * Updates the token status.  Sets isValidToken to status && the status of the other error type.
   * If status is true, we clear the wizard's error message for this type; if it is false, we set it to errorMessage.
   *
   * @param status The new isValidToken value.
   * @param errorMessage The new error message.
   * @param type The type of the error (either TOKEN or SELECTION).
   */
  private void setTokenStatus (boolean status, String errorMessage, int type)
  {
    boolean otherTypeStatus =     (type == TOKEN) ? 
                                  currentErrorMessages[SELECTION] == null :
                                  currentErrorMessages[TOKEN] == null;
    
    isValidToken = status && otherTypeStatus;
    add.setEnabled(isValidToken);

    if (status)
    {
      displayErrorMessage(null, type);
    }
    else
    {
    	if (errorMessage != null && errorMessage.trim().equals("")) // when there is no error message available.
    	{
        displayErrorMessage(XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_TOKEN_ERROR"),
                           type);
      }
      else
      {
        displayErrorMessage(errorMessage, type);
      }
    }
  }

  
  /**
   * Updates the token status.  Sets isValidToken to status && the status of the other error type.
   * Also clears the wizard's error message for this type.
   * Usually used to set isValidToken to true.
   *
   * @param status The new isValidToken value.
   * @param type The type of the error (either TOKEN or SELECTION).
   */
  private void setTokenStatus(boolean status, int type)
  {
    setTokenStatus(status, null, type);
  }



  /**
   * Sets the enabled status of the text fields and labels associated with the specified quantifier.
   * If status is true, then fields and labels associated with other quantifiers are disabled.
   * @param quantifier The quantifier whose elements' enabled status we wish to change
   *   (as enumerated in RegexNode).
   * @param status The new status of the elements.  If true, then all elements associated with other buttons
   *               are disabled.
   */    
  private void setEnabledStatus(int quantifier, boolean status)
  {
    switch (quantifier)
    {
    
    case RegexNode.REPEAT:
      repeatValue.setEnabled(status);
      if (status)
      {
        rangeMinValue.setEnabled(false);
        rangeMaxValue.setEnabled(false);
        rangeToLabel.setEnabled(false);
      }
      break;

    case RegexNode.RANGE:
      rangeMinValue.setEnabled(status);
      rangeMaxValue.setEnabled(status);
      rangeToLabel.setEnabled(status);
      if (status)
      {
        repeatValue.setEnabled(false);
      }
      break;

    }
  }

  /**
   * Checks to see if there is a selection in value.  If there is not, we set the Wizard's error message accordingly.
   * If there is, we update the contents of node.  If "Current Selection" is not the current token, then
   * we clear the Selection error message.
   */
  private void updateCurrentSelectionStatus()
  {
    if (terms.getSelectionIndex() == RegexNode.SELECTION)
    {
      String selection = value.getSelectionText();
      if (selection.equals(""))
      {
        setTokenStatus(false, XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_SELECTION_ERROR"), SELECTION);
      }
      else
      {
        setTokenStatus(true, SELECTION);
        node.setContents(selection);
        node.setHasParens(true);
      }
    }
    else
    {
      setTokenStatus(true, SELECTION);
    }
  }

  /**
   * Updates the enabled status of the auto-escape checkbox.  If status is true, we enable the checkbox, and
   * set its selection status and node's auto-escape status to the value of autoEscapeStatus.  If status is
   * false, then we disable and deselect the checkbox, and set node's status to false.
   *
   * @param status The new enabled status.
   */
  private void setEscapeCheckboxEnabledStatus(boolean status)
  {
    if (status)
    {
      escapeCheckbox.setEnabled(true);
      escapeCheckbox.setSelection(autoEscapeStatus);
      node.setAutoEscapeStatus(autoEscapeStatus);
    }
    else
    {
      escapeCheckbox.setEnabled(false);
      escapeCheckbox.setSelection(false);
      node.setAutoEscapeStatus(false);
    }
  }


  /**
   * Returns the current regex flags.
   */
  String getFlags()
  {
    return regexFlags;
  }

  /**
   * Returns the current XSDPattern model.
   */
  XSDPatternFacet getPattern()
  {
    return pattern;
  }


  /**
   * Returns a string consisting of the values of min, max, and repeat stored in node.
   * Used for debugging purposes only.
   */  
  private String getAllFieldValues()
  {
      String result = "";
      result += "Min: " + node.getMin() + "\n";
      result += "Max: " + node.getMax() + "\n";
      result += "Repeat: " + node.getRepeat() + "\n";
      result += "\n";
      return result;
  }
  

  /* Listener for the add button. */
  class ButtonSelectListener implements SelectionListener
  {
    public void widgetDefaultSelected(SelectionEvent e)
    {
    }

    // Precondition: isValidToken == true  
    public void widgetSelected(SelectionEvent e)
    {
      if (!isValidToken) // should never happen
      {
        return;
      }

      // Whether there is anything selected in value.
      boolean isActiveSelection = value.getSelectionCount() != 0;
      
      value.insert(node.toString());

      if (terms.getSelectionIndex() == RegexNode.SELECTION)
      {
        updateCurrentSelectionStatus();
      }

      // If nothing is selected, then we need to advance the caret location.
      if (!isActiveSelection)
      {
        value.setCaretOffset(value.getCaretOffset() + node.toString().length());
      }

      value.setFocus();

    }

  }
 

  /* Listener for the terms combo box. */
  class ComboListener implements Listener
  {
    public void handleEvent(Event e)
    {
      
      updateCurrentSelectionStatus();

      // If the user has typed in a token
      if (terms.getSelectionIndex() == -1)
      {
        setEscapeCheckboxEnabledStatus(true);
        node.setContents(terms.getText());
        node.setHasParens(true);
        

        if (debug)
        {
          System.out.println(terms.getText());
        }

      }
      else if (terms.getSelectionIndex() == RegexNode.SELECTION)
      {
        setEscapeCheckboxEnabledStatus(false);
      }
      else
      {
        node.setContents(RegexNode.getRegexTermValue(terms.getSelectionIndex()));
        node.setHasParens(false);
        setEscapeCheckboxEnabledStatus(false);
      }
    }
  }


  /* Listener for enabling/disabling caretLabel. */
  class TextFocusListener implements FocusListener
  {
    public void focusGained(FocusEvent e)
    {
      setShowCaretLabel(false);
    }
    public void focusLost(FocusEvent e)
    {
      setShowCaretLabel(true);
    }
  }



  /* Listener for the text fields. */
  class TextListener implements Listener
  {
    public void handleEvent (Event e)
    {

      if (debug)
      {
        System.out.println("Inside TextListener handler");  //$NON-NLS-1$
        System.out.println(e);
        System.out.println(getAllFieldValues());
      }


      if ( (e.widget == value) && (e.type == SWT.Modify) )
      {
        pattern.setLexicalValue(value.getText());
        validateRegex();
      }

      else if (e.widget == value && e.type == SWT.Selection)
      {
        if (terms.getSelectionIndex() == RegexNode.SELECTION)
        {
          updateCurrentSelectionStatus();
        }
      }

      else if (e.widget == rangeMinValue)
      {
        boolean isValid = node.setMin(rangeMinValue.getText());

        if (isValid)
        {
          setTokenStatus(true, null, TOKEN);
        }
        else
        {
          setTokenStatus(false,  XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_MIN_ERROR_SUFFIX"), TOKEN);
        }
      }

      else if (e.widget == rangeMaxValue)
      {
        boolean isValid = node.setMax(rangeMaxValue.getText());

        if (node.getMin() == RegexNode.EMPTY)
        {
          setTokenStatus(false, XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_MISSING_MIN_ERROR_SUFFIX"), TOKEN);
        }
        else if (isValid)
        {
          setTokenStatus(true, null, TOKEN);
        }
        else
        {
          setTokenStatus(false, XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_MAX_ERROR_SUFFIX"), TOKEN);
        }
      }

      else  // (e.widget == repeatValue)
      {
        boolean isValid = node.setRepeat(repeatValue.getText());
        if (isValid)
        {
          setTokenStatus(true, null, TOKEN);
        }
        else
        {
          setTokenStatus(false, XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_REPEAT_ERROR_SUFFIX"), TOKEN);
        }
      }
    }
  }

  /* Listener for the auto-escape checkbox. */
  class CheckboxListener implements SelectionListener
  {
    public void widgetDefaultSelected(SelectionEvent e)
    {
    }

    public void widgetSelected(SelectionEvent e)
    {
      boolean newStatus = !autoEscapeStatus;
      node.setAutoEscapeStatus(newStatus);
      autoEscapeStatus = newStatus;
      
      if (debug)
      {
        System.out.println("AutoEscape Status: " + node.getAutoEscapeStatus());  //$NON-NLS-1$ 
      }
    }

  }


  /* Listener for the radio buttons. */
  class RadioSelectListener implements SelectionListener
  {
    public void widgetDefaultSelected(SelectionEvent e)
    {
    }

    public void widgetSelected(SelectionEvent e)
    {
      if (debug)
      {
        System.out.println(getAllFieldValues());
      }


      int currentQuantifier = getQuantifier(e);

      node.setQuantifier(currentQuantifier);

      switch (currentQuantifier)
      {
      case RegexNode.SINGLE:                     
      case RegexNode.STAR:
      case RegexNode.PLUS:
      case RegexNode.OPTIONAL:
        setEnabledStatus(RegexNode.REPEAT, false);
        setEnabledStatus(RegexNode.RANGE, false);
        setTokenStatus(true, TOKEN);
        break; 

      case RegexNode.REPEAT:
        setEnabledStatus(RegexNode.REPEAT, true);
        setTokenStatus(node.hasValidRepeat(), XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_REPEAT_ERROR_SUFFIX"), TOKEN);
        repeatValue.setFocus();
        break;

      case RegexNode.RANGE:
        setEnabledStatus(RegexNode.RANGE, true);
        String error = (node.hasValidMin()) ? 
                            XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_MAX_ERROR_SUFFIX") : 
                            XSDEditorPlugin.getXSDString("_UI_REGEX_WIZARD_INVALID_MIN_ERROR_SUFFIX");

        setTokenStatus( node.hasValidMin() && node.hasValidMax(), error, TOKEN);
        rangeMinValue.setFocus();
        break;
      }
    }

    private int getQuantifier(SelectionEvent e)
    {

      if (e.widget == singleRadio)
      {
        return RegexNode.SINGLE;
      }
      
      else if (e.widget == starRadio)
      {
        return RegexNode.STAR;
      }
      
      else if (e.widget == plusRadio)
      {
        return RegexNode.PLUS;
      }
      
      else if (e.widget == optionalRadio)
      {
        return RegexNode.OPTIONAL;
      }
      
      else if (e.widget == repeatRadio)
      {
        return RegexNode.REPEAT;
      }
      
      else if (e.widget == rangeRadio)
      {
        return RegexNode.RANGE;
      }
      
      else // can't get here
      { 
        return RegexNode.EMPTY;
      }
    } 
  }
}
