/*
   * Adds a field to the format being composed
   */
  public void addField() {
    DefaultMutableTreeNode node =
        (DefaultMutableTreeNode) availableFieldsComp.getTree().getLastSelectedPathComponent();
    if (node == null
        || !node.isLeaf()
        || !(node.getUserObject() instanceof DataObjDataFieldWrapper)) {
      return; // not really a field that can be added, just empty or a string
    }

    Object obj = node.getUserObject();
    if (obj instanceof DataObjDataFieldWrapper) {
      DataObjDataFieldWrapper wrapper = (DataObjDataFieldWrapper) obj;
      String sep = sepText.getText();
      if (StringUtils.isNotEmpty(sep)) {
        try {
          DefaultStyledDocument doc = (DefaultStyledDocument) formatEditor.getStyledDocument();
          if (doc.getLength() > 0) {
            doc.insertString(doc.getLength(), sep, null);
          }
        } catch (BadLocationException ble) {
        }
      }
      insertFieldIntoTextEditor(wrapper);
      setHasChanged(true);
    }
  }
  public void addFieldListeners() {
    // action listener for add field button
    addFieldBtn.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            addField();
          }
        });

    // mouse adapter to detect double-click on list of available fields
    availableFieldsComp.addMouseListener(
        new MouseAdapter() {
          public void mouseClicked(MouseEvent e) {
            if (e.getClickCount() == 2) {
              addField();
            }
          }
        });
  }
  /* (non-Javadoc)
   * @see edu.ku.brc.ui.forms.formatters.DataObjFieldFormatPanelBuilder#buildUI()
   */
  protected void buildUI() {
    CellConstraints cc = new CellConstraints();

    JLabel currentFieldsLbl = createI18NLabel("DOF_DISPLAY_FORMAT");
    formatEditor = new JTextPane();
    // to make sure the component shrinks with the dialog
    formatEditor.setMinimumSize(new Dimension(200, 50));
    formatEditor.setPreferredSize(new Dimension(350, 100));

    formatEditor
        .getDocument()
        .addDocumentListener(
            new DocumentAdaptor() {
              @Override
              public void changed(DocumentEvent e) {
                updateUIEnabled();
              }
            });

    PanelBuilder addFieldPB = new PanelBuilder(new FormLayout("p,2px,p,f:p:g,r:m", "p,2px,p"));
    sepText = createTextField(4);
    addFieldBtn = createButton(getResourceString("DOF_ADD_FIELD"));
    sepLbl = createI18NFormLabel("DOF_SEP_TXT");

    addFieldPB.add(sepLbl, cc.xy(1, 1));
    addFieldPB.add(sepText, cc.xy(3, 1));
    addFieldPB.add(addFieldBtn, cc.xy(5, 1));

    sepText.setDocument(new FilteredDoc());

    addFieldBtn.setEnabled(false);
    sepLbl.setEnabled(false);
    sepText.setEnabled(false);

    // For when it is standalone
    if (AppPreferences.hasRemotePrefs()) {
      sepText.setText(AppPreferences.getRemote().get("DOF_SEP", ", "));

    } else {
      sepText.setText(", ");
    }

    PanelBuilder pb =
        new PanelBuilder(
            new FormLayout(
                "f:d:g",
                "10px,"
                    + // empty space on top of panel
                    "p,f:p:g,"
                    + // Label & format text editor
                    "2px,p,"
                    + // separator & add field
                    "10px,p,"
                    + // separator & label
                    "f:250px:g," // list box for available fields
                ),
            this);

    // layout components on main panel
    int y = 2; // leave first row blank

    pb.add(currentFieldsLbl, cc.xy(1, y));
    y += 1;
    pb.add(UIHelper.createScrollPane(formatEditor), cc.xy(1, y));
    y += 2;

    pb.add(addFieldPB.getPanel(), cc.xy(1, y));
    y += 2;

    JLabel availableFieldsLbl = createI18NFormLabel("DOF_AVAILABLE_FIELDS", SwingConstants.LEFT);
    pb.add(availableFieldsLbl, cc.xy(1, y));
    y += 1;

    // create field tree that will be re-used in all instances of single switch formatter editing
    // panel
    availableFieldsComp =
        new AvailableFieldsComponent(
            tableInfo, dataObjFieldFormatMgrCache, uiFieldFormatterMgrCache);

    pb.add(UIHelper.createScrollPane(availableFieldsComp.getTree()), cc.xy(1, y));
    y += 2;

    availableFieldsComp
        .getTree()
        .addTreeSelectionListener(
            new TreeSelectionListener() {
              @Override
              public void valueChanged(TreeSelectionEvent e) {
                boolean enable = availableFieldsComp.getTree().getSelectionCount() > 0;
                addFieldBtn.setEnabled(enable);
                sepText.setEnabled(enable);
                sepLbl.setEnabled(enable);
              }
            });

    this.mainPanelBuilder = pb;

    fillWithObjFormatter(formatContainer.getSelectedFormatter());

    addFormatTextListeners();

    // must be called after list of available fields has been created
    addFieldListeners();
  }