/**
   * This helper method puts the step configuration stored in the meta object and puts it into the
   * dialog controls.
   */
  private void populateDialog() {
    wRemoveBlanks.setSelection(meta.isConsecutiveDelimsAsOne());
    if (meta.getSourceFields() != null) {
      for (int i = 0; i < meta.getSourceFields().length; i++) {
        TableItem item = wGroup.table.getItem(i);
        if (meta.getSourceFields()[i] != null) {
          item.setText(1, meta.getSourceFields()[i]);
        }
        if (meta.getSourceDelims()[i] != null) {
          item.setText(2, meta.getSourceDelims()[i]);
        }
        if (meta.getOutputFields()[i] != null) {
          item.setText(3, meta.getOutputFields()[i]);
        }
        if (meta.getOutputDelims()[i] != null) {
          item.setText(4, meta.getOutputDelims()[i]);
        }
      }
    }

    wGroup.setRowNums();
    wGroup.optWidth(true);

    wStepname.selectAll();
    wStepname.setFocus();
  }
  /** Called when the user confirms the dialog */
  private void ok() {
    // The "stepname" variable will be the return value for the open() method.
    // Setting to step name from the dialog control
    stepname = wStepname.getText();
    // Setting the  settings to the meta object
    meta.setConsecutiveDelimsAsOne(wRemoveBlanks.getSelection());
    int nrfields = wGroup.nrNonEmpty();
    meta.allocate(nrfields);
    for (int i = 0; i < nrfields; i++) {
      TableItem item = wGroup.getNonEmpty(i);
      meta.getSourceFields()[i] = item.getText(1);
      meta.getSourceDelims()[i] = item.getText(2);
      meta.getOutputFields()[i] = item.getText(3);
      meta.getOutputDelims()[i] = item.getText(4);
    }

    // close the SWT dialog window
    dispose();
  }
  /**
   * This method is called by Spoon when the user opens the settings dialog of the step. It should
   * open the dialog and return only once the dialog has been closed by the user.
   *
   * <p>If the user confirms the dialog, the meta object (passed in the constructor) must be updated
   * to reflect the new step settings. The changed flag of the meta object must reflect whether the
   * step configuration was changed by the dialog.
   *
   * <p>If the user cancels the dialog, the meta object must not be updated, and its changed flag
   * must remain unaltered.
   *
   * <p>The open() method must return the name of the step after the user has confirmed the dialog,
   * or null if the user cancelled the dialog.
   */
  public String open() {

    // store some convenient SWT variables
    Shell parent = getParent();
    Display display = parent.getDisplay();

    // SWT code for preparing the dialog
    shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN | SWT.MAX);
    props.setLook(shell);
    setShellImage(shell, meta);

    // Save the value of the changed flag on the meta object. If the user cancels
    // the dialog, it will be restored to this saved value.
    // The "changed" variable is inherited from BaseStepDialog
    changed = meta.hasChanged();

    // The ModifyListener used on all controls. It will update the meta object to
    // indicate that changes are being made.
    ModifyListener lsMod =
        new ModifyListener() {
          public void modifyText(ModifyEvent e) {
            meta.setChanged();
          }
        };

    // ------------------------------------------------------- //
    // SWT code for building the actual settings dialog        //
    // ------------------------------------------------------- //
    FormLayout formLayout = new FormLayout();
    formLayout.marginWidth = Const.FORM_MARGIN;
    formLayout.marginHeight = Const.FORM_MARGIN;

    shell.setLayout(formLayout);
    shell.setText(BaseMessages.getString(PKG, "UniqueListStep.Shell.Title"));

    int middle = props.getMiddlePct();
    int margin = Const.MARGIN;

    // Stepname line
    wlStepname = new Label(shell, SWT.RIGHT);
    wlStepname.setText(BaseMessages.getString(PKG, "System.Label.StepName"));
    props.setLook(wlStepname);
    fdlStepname = new FormData();
    fdlStepname.left = new FormAttachment(0, 0);
    fdlStepname.right = new FormAttachment(middle, -margin);
    fdlStepname.top = new FormAttachment(0, margin);
    wlStepname.setLayoutData(fdlStepname);

    wStepname = new Text(shell, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
    wStepname.setText(stepname);
    props.setLook(wStepname);
    wStepname.addModifyListener(lsMod);
    fdStepname = new FormData();
    fdStepname.left = new FormAttachment(middle, 0);
    fdStepname.top = new FormAttachment(0, margin);
    fdStepname.right = new FormAttachment(100, 0);
    wStepname.setLayoutData(fdStepname);

    // Treat Consecutive Delimiters as One
    //
    wlRemoveBlanks = new Label(shell, SWT.RIGHT);
    wlRemoveBlanks.setText("Treat Consecutive Delims as One");
    wlRemoveBlanks.setToolTipText(
        "Multiple delimiters in a row will be condensed. Essentially removes blank spaces");
    props.setLook(wlRemoveBlanks);
    fdlRemoveBlanks = new FormData();
    fdlRemoveBlanks.left = new FormAttachment(0, 0);
    fdlRemoveBlanks.top = new FormAttachment(wStepname, margin);
    fdlRemoveBlanks.right = new FormAttachment(middle, -margin);
    wlRemoveBlanks.setLayoutData(fdlRemoveBlanks);
    wRemoveBlanks = new Button(shell, SWT.CHECK);
    wRemoveBlanks.setToolTipText(
        "Multiple delimiters in a row will be condensed. Essentially removes blank spaces");
    props.setLook(wRemoveBlanks);
    wRemoveBlanks.addSelectionListener(
        new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            meta.setChanged();
          }
        });
    fdRemoveBlanks = new FormData();
    fdRemoveBlanks.left = new FormAttachment(middle, 0);
    fdRemoveBlanks.top = new FormAttachment(wStepname, margin);
    fdRemoveBlanks.right = new FormAttachment(100, 0);
    wRemoveBlanks.setLayoutData(fdRemoveBlanks);

    // OK and cancel buttons
    wOK = new Button(shell, SWT.PUSH);
    wOK.setText(BaseMessages.getString(PKG, "System.Button.OK"));
    wGet = new Button(shell, SWT.PUSH);
    wGet.setText("Get");
    wCancel = new Button(shell, SWT.PUSH);
    wCancel.setText(BaseMessages.getString(PKG, "System.Button.Cancel"));

    setButtonPositions(new Button[] {wOK, wGet, wCancel}, margin, null);

    wlGroup = new Label(shell, SWT.NONE);
    wlGroup.setText("Fields");
    props.setLook(wlGroup);
    fdlGroup = new FormData();
    fdlGroup.left = new FormAttachment(0, 0);
    fdlGroup.top = new FormAttachment(wlRemoveBlanks, margin);
    wlGroup.setLayoutData(fdlGroup);

    // Fields
    colinf =
        new ColumnInfo[] {
          new ColumnInfo("Field Name", ColumnInfo.COLUMN_TYPE_CCOMBO, new String[] {""}, false),
          new ColumnInfo("Current Delimiter", ColumnInfo.COLUMN_TYPE_TEXT, false),
          new ColumnInfo("Output Field Name (Optional)", ColumnInfo.COLUMN_TYPE_TEXT, false),
          new ColumnInfo("Output Delimiter (Optional)", ColumnInfo.COLUMN_TYPE_TEXT, false)
        };

    int nrRows = (meta.getSourceFields() != null ? meta.getSourceFields().length : 1);

    wGroup =
        new TableView(
            transMeta,
            shell,
            SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL,
            colinf,
            nrRows,
            lsMod,
            props);

    fdGroup = new FormData();
    fdGroup.left = new FormAttachment(0, 0);
    fdGroup.top = new FormAttachment(wlGroup, margin);
    fdGroup.right = new FormAttachment(100, 0);
    fdGroup.bottom = new FormAttachment(wGet, -margin);
    wGroup.setLayoutData(fdGroup);

    final Runnable runnable =
        new Runnable() {
          public void run() {
            StepMeta stepMeta = transMeta.findStep(stepname);
            if (stepMeta != null) {
              try {
                RowMetaInterface row = transMeta.getPrevStepFields(stepMeta);

                // Remember these fields...
                for (int i = 0; i < row.size(); i++) {
                  inputFields.put(row.getValueMeta(i).getName(), i);
                }
                setComboBoxes();
              } catch (KettleException e) {
                logError(BaseMessages.getString(PKG, "System.Dialog.GetFieldsFailed.Message"));
              }
            }
          }
        };
    new Thread(runnable).start();

    // Add listeners for cancel and OK
    lsCancel =
        new Listener() {
          public void handleEvent(Event e) {
            cancel();
          }
        };
    lsOK =
        new Listener() {
          public void handleEvent(Event e) {
            ok();
          }
        };
    lsGet =
        new Listener() {
          public void handleEvent(Event event) {
            get();
          }
        };

    wCancel.addListener(SWT.Selection, lsCancel);
    wOK.addListener(SWT.Selection, lsOK);
    wGet.addListener(SWT.Selection, lsGet);

    // default listener (for hitting "enter")
    lsDef =
        new SelectionAdapter() {
          public void widgetDefaultSelected(SelectionEvent e) {
            ok();
          }
        };
    wStepname.addSelectionListener(lsDef);

    // Detect X or ALT-F4 or something that kills this window and cancel the dialog properly
    shell.addShellListener(
        new ShellAdapter() {
          public void shellClosed(ShellEvent e) {
            cancel();
          }
        });

    // Set/Restore the dialog size based on last position on screen
    // The setSize() method is inherited from BaseStepDialog
    setSize();

    // populate the dialog with the values from the meta object
    populateDialog();

    // restore the changed flag to original value, as the modify listeners fire during dialog
    // population
    meta.setChanged(changed);

    // open dialog and enter event loop
    shell.open();
    while (!shell.isDisposed()) {
      if (!display.readAndDispatch()) display.sleep();
    }

    // at this point the dialog has closed, so either ok() or cancel() have been executed
    // The "stepname" variable is inherited from BaseStepDialog
    return stepname;
  }