Index: modules/field_ui/field_ui-rtl.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui-rtl.css,v
retrieving revision 1.1
diff -u -r1.1 field_ui-rtl.css
--- modules/field_ui/field_ui-rtl.css	19 Aug 2009 13:31:13 -0000	1.1
+++ modules/field_ui/field_ui-rtl.css	28 Oct 2009 01:24:20 -0000
@@ -1,8 +1,7 @@
 /* $Id: field_ui-rtl.css,v 1.1 2009/08/19 13:31:13 webchick Exp $ */
 
 /* 'Manage fields' overview */
-#field-overview .label-add-new-field,
-#field-overview .label-add-existing-field {
+#field-overview tr.add-row .wrapper {
   float: right;
 }
 
Index: modules/field_ui/field_ui-field-overview-form.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui-field-overview-form.tpl.php,v
retrieving revision 1.2
diff -u -r1.2 field_ui-field-overview-form.tpl.php
--- modules/field_ui/field_ui-field-overview-form.tpl.php	24 Oct 2009 17:26:16 -0000	1.2
+++ modules/field_ui/field_ui-field-overview-form.tpl.php	28 Oct 2009 01:24:20 -0000
@@ -32,63 +32,10 @@
   </thead>
   <tbody>
     <?php
-    $count = 0;
-    foreach ($rows as $row): ?>
-      <tr class="<?php print $count % 2 == 0 ? 'odd' : 'even'; ?> <?php print $row->class ?>">
-      <?php
-      switch ($row->row_type):
-        case 'field': ?>
-          <td>
-            <span class="<?php print $row->label_class; ?>"><?php print $row->label; ?></span>
-          </td>
-          <td><?php print $row->weight . $row->hidden_name; ?></td>
-          <td><?php print $row->field_name; ?></td>
-          <td><?php print $row->type; ?></td>
-          <td><?php print $row->widget_type; ?></td>
-          <td><?php print $row->edit; ?></td>
-          <td><?php print $row->delete; ?></td>
-          <?php break;
-
-        case 'extra': ?>
-          <td>
-            <span class="<?php print $row->label_class; ?>"><?php print $row->label; ?></span>
-          </td>
-          <td><?php print $row->weight . $row->hidden_name; ?></td>
-          <td><?php print $row->name; ?></td>
-          <td colspan="2"><?php print $row->description; ?></td>
-          <td><?php print $row->edit; ?></td>
-          <td><?php print $row->delete; ?></td>
-          <?php break;
-
-        case 'add_new_field': ?>
-          <td>
-            <div class="<?php print $row->label_class; ?>">
-              <div class="new"><?php print t('Add new field'); ?></div>
-              <?php print $row->label; ?>
-            </div>
-          </td>
-          <td><div class="new">&nbsp;</div><?php print $row->weight . $row->hidden_name; ?></td>
-          <td><div class="new">&nbsp;</div><?php print $row->field_name; ?></td>
-          <td><div class="new">&nbsp;</div><?php print $row->type; ?></td>
-          <td colspan="3"><div class="new">&nbsp;</div><?php print $row->widget_type; ?></td>
-          <?php break;
-
-        case 'add_existing_field': ?>
-          <td>
-            <div class="<?php print $row->label_class; ?>">
-              <div class="new"><?php print t('Add existing field'); ?></div>
-              <?php print $row->label; ?>
-            </div>
-          </td>
-          <td><div class="new">&nbsp;</div><?php print $row->weight . $row->hidden_name; ?></td>
-          <td colspan="2"><div class="new">&nbsp;</div><?php print $row->field_name; ?></td>
-          <td colspan="3"><div class="new">&nbsp;</div><?php print $row->widget_type; ?></td>
-          <?php break;
-      endswitch; ?>
-      </tr>
-      <?php $count++;
+    foreach ($row_order as $key):
+      print render($form[$key]);
     endforeach; ?>
   </tbody>
 </table>
 
-<?php print $submit; ?>
+<?php print drupal_render_children($form); ?>
Index: modules/field_ui/field_ui.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.module,v
retrieving revision 1.12
diff -u -r1.12 field_ui.module
--- modules/field_ui/field_ui.module	26 Oct 2009 00:15:59 -0000	1.12
+++ modules/field_ui/field_ui.module	28 Oct 2009 01:24:21 -0000
@@ -158,6 +158,11 @@
       'file' => 'field_ui.admin.inc',
       'template' => 'field_ui-field-overview-form',
     ),
+    'field_ui_field_overview_row' => array(
+      'render element' => 'element',
+      'file' => 'field_ui.admin.inc',
+      'template' => 'field_ui_field_overview_row',
+    ),
     'field_ui_display_overview_form' => array(
       'render element' => 'form',
       'file' => 'field_ui.admin.inc',
Index: modules/field_ui/field_ui.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.css,v
retrieving revision 1.1
diff -u -r1.1 field_ui.css
--- modules/field_ui/field_ui.css	19 Aug 2009 13:31:13 -0000	1.1
+++ modules/field_ui/field_ui.css	28 Oct 2009 01:24:21 -0000
@@ -1,17 +1,16 @@
 /* $Id: field_ui.css,v 1.1 2009/08/19 13:31:13 webchick Exp $ */
 
 /* 'Manage fields' overview */
-#field-overview .label-add-new-field,
-#field-overview .label-add-existing-field {
+#field-overview tr.add-row .wrapper {
   float: left; /* LTR */
 }
-#field-overview tr.add-new .tabledrag-changed {
+#field-overview tr.add-row .tabledrag-changed {
   display: none;
 }
-#field-overview tr.add-new .description {
+#field-overview tr.add-row .description {
   margin-bottom: 0;
 }
-#field-overview .new {
+#field-overview .label {
   font-weight: bold;
   padding-bottom: .5em;
 }
Index: modules/field_ui/field_ui.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field_ui/field_ui.admin.inc,v
retrieving revision 1.24
diff -u -r1.24 field_ui.admin.inc
--- modules/field_ui/field_ui.admin.inc	24 Oct 2009 05:26:13 -0000	1.24
+++ modules/field_ui/field_ui.admin.inc	28 Oct 2009 01:24:21 -0000
@@ -3,7 +3,7 @@
 
 /**
  * @file
- * Administrative interface for custom field type creation.
+ * Administrative interface for the Field API.
  */
 
 /**
@@ -63,7 +63,7 @@
 }
 
 /**
- * Menu callback; listing of fields for a content type.
+ * Menu callback; listing of fields for a bundle.
  *
  * Allows fields and pseudo-fields to be re-ordered.
  */
@@ -85,16 +85,23 @@
 
   $extra = field_extra_fields($bundle);
 
-  // Store each default weight so that we can add the 'add new' rows after them.
+  // Track weights so that the 'add' rows are added at the end.
   $weights = array();
 
   $form += array(
     '#tree' => TRUE,
     '#object_type' => $obj_type,
     '#bundle' => $bundle,
+    // Used in submit handler to determine the action to take for each row.
     '#fields' => array_keys($instances),
     '#extra' => array_keys($extra),
-    '#field_rows' => array(),
+    // Used at preprocess to determine the row order according to weight and
+    // nesting while keeping a flat form structure.
+    '#table_rows' => array(),
+    // Contributed modules willing to add hierarchical rows in the form should
+    // populate the #options and #default_value properties for each row's
+    // 'parent' element, and set this property to TRUE.
+    '#hierarchy' => FALSE,
   );
 
   // Fields.
@@ -130,15 +137,18 @@
         '#type' => 'hidden',
         '#default_value' => $instance['field_name'],
        ),
+       'parent' => array(
+         '#type' => 'select',
+         '#options' => array(),
+       ),
       '#row_type' => 'field',
+      '#theme' => 'field_ui_field_overview_row',
     );
 
     if (!empty($instance['locked'])) {
-      $form[$name]['edit'] = array('#value' => t('Locked'));
-      $form[$name]['delete'] = array();
-      $form[$name]['#disabled_row'] = TRUE;
+      $form[$name]['delete'] = array('#markup' => t('Locked'));
     }
-    $form['#field_rows'][] = $name;
+    $form['#table_rows'][] = $name;
     $weights[] = $weight;
   }
 
@@ -170,10 +180,14 @@
         '#type' => 'hidden',
         '#default_value' => $name,
       ),
-      '#disabled_row' => TRUE,
+      'parent' => array(
+        '#type' => 'select',
+        '#options' => array(),
+       ),
       '#row_type' => 'extra',
+      '#theme' => 'field_ui_field_overview_row',
     );
-    $form['#field_rows'][] = $name;
+    $form['#table_rows'][] = $name;
     $weights[] = $weight;
   }
 
@@ -219,10 +233,14 @@
         '#type' => 'hidden',
         '#default_value' => $name,
       ),
-      '#add_new' => TRUE,
+      'parent' => array(
+        '#type' => 'select',
+        '#options' => array(),
+       ),
       '#row_type' => 'add_new_field',
+      '#theme' => 'field_ui_field_overview_row',
     );
-    $form['#field_rows'][] = $name;
+    $form['#table_rows'][] = $name;
   }
 
   // Additional row: add existing field.
@@ -256,10 +274,14 @@
         '#type' => 'hidden',
         '#default_value' => $name,
       ),
-      '#add_new' => TRUE,
+      'parent' => array(
+        '#type' => 'select',
+        '#options' => array(),
+       ),
       '#row_type' => 'add_existing_field',
+      '#theme' => 'field_ui_field_overview_row'
     );
-    $form['#field_rows'][] = $name;
+    $form['#table_rows'][] = $name;
   }
 
   $form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
@@ -274,7 +296,11 @@
 
   drupal_add_css(drupal_get_path('module', 'field_ui') . '/field_ui.css');
   drupal_add_tabledrag('field-overview', 'order', 'sibling', 'field-weight');
+  if ($form['#hierarchy']) {
+    drupal_add_tabledrag('field-overview', 'match', 'parent', 'field-parent', 'field-parent', 'field-name');
+  }
   drupal_add_js(drupal_get_path('module', 'field_ui') . '/field_ui.js');
+
   // Add settings for the update selects behavior.
   $js_fields = array();
   foreach (field_ui_existing_field_options($form['#object_type'], $form['#bundle']) as $field_name => $fields) {
@@ -284,52 +310,54 @@
   }
   drupal_add_js(array('fieldWidgetTypes' => field_ui_widget_type_options(), 'fields' => $js_fields), 'setting');
 
-  $order = _field_ui_overview_order($form, $form['#field_rows']);
-  $rows = array();
+  $row_order = _field_ui_overview_order($form, $form['#table_rows']);
+  $vars['row_order'] = $row_order;
 
-  // Identify the 'new item' keys in the form.
-  $keys = array_keys($form);
-  $add_rows = array();
-  foreach ($keys as $key) {
-    if (substr($key, 0, 4) == '_add') {
-      $add_rows[] = $key;
-    }
-  }
-  while ($order) {
-    $key = reset($order);
+  $count = 0;
+  foreach ($row_order as $key) {
     $element = &$form[$key];
-    $row = new stdClass();
 
-    // Add target classes for the tabledrag behavior.
-    $element['weight']['#attributes']['class'][] = 'field-weight';
-    $element['hidden_name']['#attributes']['class'][] = 'field-name';
-    // Add target classes for the update selects behavior.
-    switch ($element['#row_type']) {
-      case 'add_new_field':
-        $element['type']['#attributes']['class'][] = 'field-type-select';
-        $element['widget_type']['#attributes']['class'][] = 'widget-type-select';
-        break;
-
-      case 'add_existing_field':
-        $element['field_name']['#attributes']['class'][] = 'field-select';
-        $element['widget_type']['#attributes']['class'][] = 'widget-type-select';
-        $element['label']['#attributes']['class'][] = 'label-textfield';
-        break;
+    // Add target classes for the tabledrag 'order' behavior.
+    if (isset($element['weight'])) {
+      $element['weight']['#attributes']['class'][] = 'field-weight';
     }
-    foreach (element_children($element) as $child) {
-      $row->{$child} = drupal_render($element[$child]);
+    // Add target classes for the tabledrag 'match' behavior if the form is
+    // hierarchical, or remove the 'parent' selector.
+    if ($form['#hierarchy']) {
+      $element['parent']['#attributes']['class'][] = 'field-parent';
+      $element['hidden_name']['#attributes']['class'][] = 'field-name';
+    }
+    elseif (isset($element['parent'])) {
+      $element['parent'] = array('#markup' => '');
     }
-    $row->label_class = 'label-' . strtr($element['#row_type'], '_', '-');
-    $row->row_type = $element['#row_type'];
-    $row->class = 'draggable';
-    $row->class .= isset($element['#add_new']) ? ' add-new' : '';
-    $row->class .= isset($element['#disabled_row']) ? ' menu-disabled' : '';
 
-    $rows[] = $row;
-    array_shift($order);
+    // Add striping.
+    $element['#zebra'] = $count % 2 == 0 ? 'odd' : 'even';
+    $count++;
+  }
+}
+
+/**
+ * Theme preprocess function for field_ui_field_overview_row.tpl.php.
+ */
+function template_preprocess_field_ui_field_overview_row(&$vars) {
+  $element = &$vars['element'];
+
+  $vars['zebra'] = $element['#zebra'];
+
+  switch ($element['#row_type']) {
+    case 'add_new_field':
+      // Add target classes for the update selects behavior.
+      $element['type']['#attributes']['class'][] = 'field-type-select';
+      $element['widget_type']['#attributes']['class'][] = 'widget-type-select';
+      break;
+    case 'add_existing_field':
+      // Add target classes for the update selects behavior.
+      $element['field_name']['#attributes']['class'][] = 'field-select';
+      $element['widget_type']['#attributes']['class'][] = 'widget-type-select';
+      $element['label']['#attributes']['class'][] = 'label-textfield';
+      break;
   }
-  $vars['rows'] = $rows;
-  $vars['submit'] = drupal_render_children($form);
 }
 
 /**
@@ -552,7 +580,7 @@
 }
 
 /**
- * Menu callback; presents a listing of fields display settings for a content type.
+ * Menu callback; presents a listing of fields display settings for a bundle.
  *
  * This form includes form widgets to select which fields appear in teaser and
  * full build modes, and how the field labels should be rendered.
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.387
diff -u -r1.387 form.inc
--- includes/form.inc	27 Oct 2009 04:12:39 -0000	1.387
+++ includes/form.inc	28 Oct 2009 01:24:20 -0000
@@ -3046,7 +3046,7 @@
   $batch =& batch_get();
 
   drupal_theme_initialize();
-  
+
   if (isset($batch)) {
     // Add process information
     $process_info = array(
@@ -3061,7 +3061,7 @@
     );
     $batch += $process_info;
 
-    // The batch is now completely built. Allow other modules to make changes to the 
+    // The batch is now completely built. Allow other modules to make changes to the
     // batch so that it is easier to reuse batch processes in other enviroments.
     drupal_alter('batch', $batch);
 
Index: modules/field_ui/field_ui_field_overview_row.tpl.php
===================================================================
RCS file: modules/field_ui/field_ui_field_overview_row.tpl.php
diff -N modules/field_ui/field_ui_field_overview_row.tpl.php
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ modules/field_ui/field_ui_field_overview_row.tpl.php	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,64 @@
+<?php
+// $Id: field_ui-field-overview-form.tpl.php,v 1.2 2009/10/24 17:26:16 webchick Exp $
+
+/**
+ * @file
+ * TODO
+ *
+ * @see template_preprocess_field_ui_field_overview_row()
+ */
+?>
+<?php switch ($element['#row_type']) :
+  case 'field': ?>
+    <tr class="draggable <?php print $zebra ?>">
+      <td><?php print render($element['label']); ?></td>
+      <td><?php print render($element['weight']) . render($element['parent']) . render($element['hidden_name']); ?></td>
+      <td><?php print render($element['field_name']); ?></td>
+      <td><?php print render($element['type']); ?></td>
+      <td><?php print render($element['widget_type']); ?></td>
+      <td><?php print render($element['edit']); ?></td>
+      <td><?php print render($element['delete']); ?></td>
+    </tr>
+    <?php break;
+
+  case 'extra': ?>
+    <tr class="draggable menu-disabled <?php print $zebra ?>">
+      <td><?php print render($element['label']); ?></td>
+      <td><?php print render($element['weight']) . render($element['parent']) . render($element['hidden_name']); ?></td>
+      <td><?php print render($element['name']); ?></td>
+      <td colspan="2"><?php print render($element['description']); ?></td>
+      <td><?php print render($element['edit']); ?></td>
+      <td><?php print render($element['delete']); ?></td>
+    </tr>
+    <?php break;
+
+  case 'add_new_field': ?>
+    <tr class="draggable add-row <?php print $zebra ?>">
+      <td>
+        <div class="wrapper">
+          <div class="label"><?php print t('Add new field'); ?></div>
+          <?php print render($element['label']); ?>
+        </div>
+      </td>
+      <td><div class="label">&nbsp;</div><?php print render($element['weight']) . render($element['parent']) . render($element['hidden_name']); ?></td>
+      <td><div class="label">&nbsp;</div><?php print render($element['field_name']); ?></td>
+      <td><div class="label">&nbsp;</div><?php print render($element['type']); ?></td>
+      <td colspan="3"><div class="label">&nbsp;</div><?php print render($element['widget_type']); ?></td>
+    </tr>
+    <?php break;
+
+  case 'add_existing_field': ?>
+    <tr class="draggable add-row <?php print $zebra ?>">
+      <td>
+        <div class="wrapper">
+          <div class="label"><?php print t('Add existing field'); ?></div>
+          <?php print render($element['label']); ?>
+        </div>
+      </td>
+      <td><div class="label">&nbsp;</div><?php print render($element['weight']) . render($element['parent']) . render($element['hidden_name']); ?></td>
+      <td colspan="2"><div class="label">&nbsp;</div><?php print render($element['field_name']); ?></td>
+      <td colspan="3"><div class="label">&nbsp;</div><?php print render($element['widget_type']); ?></td>
+    </tr>
+    <?php break;
+endswitch; ?>
+
