ui/src/main/java/ucar/util/prefs/ui/PrefPanel.java
public void finish( boolean addButtons, String where) {
    if (finished)
      throw new IllegalStateException("PrefPanel "+name+": already called finish()");  

    StringBuilder sbuff = new StringBuilder();

    // column layout, first sort by col
    Collections.sort(layoutComponents, new Comparator<LayoutComponent>() {
      public int compare(LayoutComponent o1, LayoutComponent o2) {
        return o1.col - o2.col;
      }
      public boolean equals(Object o1) { return o1 == this; }
    });

    // now create column layout spec and x cell constraint
    sbuff.setLength(0);
    int currCol = -1;
    Iterator iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();
      if (lc.col > currCol) {
        if (currCol >= 0)
          sbuff.append(", 5dlu, ");
        else
          sbuff.append("3dlu, ");
        sbuff.append( "right:default, 3dlu, default:grow");
        currCol += 2;
      }
      lc.ccLabel.gridX = 2*lc.col+2;
      lc.cc.gridX = 2*lc.col+4;
    }
    String colSpec = sbuff.toString();
    if (debugLayout) System.out.println(" column layout = "+ colSpec);
    int ncols = 2*currCol;

    // row layout, first sort by row
    Collections.sort(layoutComponents, new Comparator<LayoutComponent>() {
      public int compare(LayoutComponent o1, LayoutComponent o2) {
        return o1.row - o2.row;
      }
      public boolean equals(Object o1) { return o1 == this; }
    });

    // now adjust for any headings, put into y cell constraint
    int incr = 0;
    iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();
      if ((lc.comp instanceof String) && (lc.row > 0)) // its a header, not in first position
        incr++; // leave space by adding a row

      lc.cc.gridY = lc.row + incr + 1; // adjust downward
      lc.ccLabel.gridY = lc.cc.gridY;
      if (debugLayout) System.out.println(lc+" constraint = "+ lc.cc);
    }

    // now create row layout spec
    sbuff.setLength(0);
    int currRow = -1;
    iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();
      while (lc.row > currRow) {
        if ((lc.comp instanceof String) && (lc.row > 0)) {
          sbuff.append( ", 5dlu, default");
        } else if ((lc.comp == null)) {
          sbuff.append(", ").append(lc.col).append("dlu");
        } else {
          if (currRow >= 0) sbuff.append(", ");
          sbuff.append("default");
        }
        currRow++;
      }
    }
    String rowSpec = sbuff.toString();
    if (debugLayout) System.out.println(" row layout = "+ rowSpec);

    // the jgoodies form layout
    FormLayout layout = new FormLayout( colSpec, rowSpec);

    PanelBuilder builder = new PanelBuilder(layout);
    builder.setDefaultDialogBorder();

    CellConstraints cc = new CellConstraints();

    // now add each component with correct constraint
    iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();

      if (lc.comp instanceof Field) {
        Field fld = (Field) lc.comp;
        builder.addLabel( fld.getLabel()+":", lc.ccLabel);
        Component comp = fld.getEditComponent();
        if (lc.comp instanceof Field.TextArea)
          comp= new JScrollPane( comp);
        builder.add( comp,  lc.cc);
      } else if (lc.comp instanceof String) {
         String header = (String) lc.comp;
         builder.addSeparator(header, cc.xyw(1, lc.cc.gridY, ncols));
      }  else if (lc.comp instanceof Component) {
         builder.add( (Component) lc.comp,  lc.cc);
      }
    }

    mainPanel =  builder.getPanel();

      // button panel
    JPanel buttPanel = new JPanel();
    JButton acceptButton = new JButton("Apply");
    buttPanel.add(acceptButton, null);
    for (JComponent auxButton : auxButtons)
      buttPanel.add( auxButton, null);

      // button listeners
    acceptButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        accept();
      }
    });

    setLayout( new BorderLayout());
    add(mainPanel, BorderLayout.CENTER);

    if (addButtons) {
      if (where.equals( BorderLayout.SOUTH)) {
        JPanel south = new JPanel();
        south.setLayout(new BoxLayout( south, BoxLayout.Y_AXIS));
        south.add( new JSeparator(SwingConstants.HORIZONTAL));
        south.add( buttPanel);
        add( south, BorderLayout.SOUTH);
      } else
        add(buttPanel, where);
    }

    finished = true;
  }
public void finish( boolean addButtons, String where) {
    if (finished)
      throw new IllegalStateException("PrefPanel "+name+": already called finish()");  

    StringBuilder sbuff = new StringBuilder();

    // column layout, first sort by col
    Collections.sort(layoutComponents, new Comparator<LayoutComponent>() {
      public int compare(LayoutComponent o1, LayoutComponent o2) {
        return o1.col - o2.col;
      }
      public boolean equals(Object o1) { return o1 == this; }
    });

    // now create column layout spec and x cell constraint
    sbuff.setLength(0);
    int currCol = -1;
    Iterator iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();
      if (lc.col > currCol) {
        if (currCol >= 0)
          sbuff.append(", 5dlu, ");
        else
          sbuff.append("3dlu, ");
        sbuff.append( "right:default, 3dlu, default:grow");
        currCol += 2;
      }
      lc.ccLabel.gridX = 2*lc.col+2;
      lc.cc.gridX = 2*lc.col+4;
    }
    String colSpec = sbuff.toString();
    if (debugLayout) System.out.println(" column layout = "+ colSpec);
    int ncols = 2*currCol;

    // row layout, first sort by row
    Collections.sort(layoutComponents, new Comparator<LayoutComponent>() {
      public int compare(LayoutComponent o1, LayoutComponent o2) {
        return o1.row - o2.row;
      }
      public boolean equals(Object o1) { return o1 == this; }
    });

    // now adjust for any headings, put into y cell constraint
    int incr = 0;
    iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();
      if ((lc.comp instanceof String) && (lc.row > 0)) // its a header, not in first position
        incr++; // leave space by adding a row

      lc.cc.gridY = lc.row + incr + 1; // adjust downward
      lc.ccLabel.gridY = lc.cc.gridY;
      if (debugLayout) System.out.println(lc+" constraint = "+ lc.cc);
    }

    // now create row layout spec
    sbuff.setLength(0);
    int currRow = -1;
    iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();
      while (lc.row > currRow) {
        if ((lc.comp instanceof String) && (lc.row > 0)) {
          sbuff.append( ", 5dlu, default");
        } else if ((lc.comp == null)) {
          sbuff.append(", ").append(lc.col).append("dlu");
        } else {
          if (currRow >= 0) sbuff.append(", ");
          sbuff.append("default");
        }
        currRow++;
      }
    }
    String rowSpec = sbuff.toString();
    if (debugLayout) System.out.println(" row layout = "+ rowSpec);

    // the jgoodies form layout
    FormLayout layout = new FormLayout( colSpec, rowSpec);

    PanelBuilder builder = new PanelBuilder(layout);
    builder.setDefaultDialogBorder();

    CellConstraints cc = new CellConstraints();

    // now add each component with correct constraint
    iter = layoutComponents.iterator();
    while (iter.hasNext()) {
      LayoutComponent lc = (LayoutComponent) iter.next();

      if (lc.comp instanceof Field) {
        Field fld = (Field) lc.comp;
        builder.addLabel( fld.getLabel()+":", lc.ccLabel);
        Component comp = fld.getEditComponent();
        if (lc.comp instanceof Field.TextArea)
          comp= new JScrollPane( comp);
        builder.add( comp,  lc.cc);
      } else if (lc.comp instanceof String) {
         String header = (String) lc.comp;
         builder.addSeparator(header, cc.xyw(1, lc.cc.gridY, ncols));
      }  else if (lc.comp instanceof Component) {
         builder.add( (Component) lc.comp,  lc.cc);
      }
    }

    mainPanel =  builder.getPanel();

      // button panel
    JPanel buttPanel = new JPanel();
    JButton acceptButton = new JButton("Apply");
    buttPanel.add(acceptButton, null);
    for (JComponent auxButton : auxButtons)
      buttPanel.add( auxButton, null);

      // button listeners
    acceptButton.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        accept();
      }
    });

    setLayout( new BorderLayout());
    add(mainPanel, BorderLayout.CENTER);

    if (addButtons) {
      if (where.equals( BorderLayout.SOUTH)) {
        JPanel south = new JPanel();
        south.setLayout(new BoxLayout( south, BoxLayout.Y_AXIS));
        south.add( new JSeparator(SwingConstants.HORIZONTAL));
        south.add( buttPanel);
        add( south, BorderLayout.SOUTH);
      } else
        add(buttPanel, where);
    }

    finished = true;
  }
Call when finished adding components to the PrefPanel.
@param addButtons if true, add buttons
@param where BorderLayout.NORTH, SOUTH, EAST, WEST