Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1247
diff -u -p -r1.1247 common.inc
--- includes/common.inc	28 Oct 2010 02:00:27 -0000	1.1247
+++ includes/common.inc	3 Nov 2010 16:54:46 -0000
@@ -5264,6 +5264,98 @@ function drupal_pre_render_markup($eleme
 }
 
 /**
+ * #pre_render callback to transform children of an element into #rows suitable for theme_table().
+ *
+ * This function converts sub-elements of an element of #type 'table' to be
+ * suitable for theme_table():
+ * - The first level of sub-elements are table rows. Only the #attributes
+ *   property is taken into account.
+ * - The second level of sub-elements is converted into columns for the
+ *   corresponding first-level table row.
+ *
+ * Simple example usage:
+ * @code
+ * $form['table'] = array(
+ *   '#type' => 'table',
+ *   '#header' => array(t('Title'), array('data' => t('Operations'), 'colspan' => '1')),
+ *   // Optionally, to add tableDrag support:
+ *   '#attached' => array(
+ *     'tabledrag' => array(array('order', 'sibling', 'thing-weight')),
+ *   ),
+ * );
+ * foreach ($things as $row => $thing) {
+ *   $form['table'][$row]['#weight'] = $thing['weight'];
+ *
+ *   $form['table'][$row]['title'] = array(
+ *     '#type' => 'textfield',
+ *     '#default_value' => $thing['title'],
+ *   );
+ *
+ *   // Optionally, to add tableDrag support:
+ *   $form['table'][$row]['#attributes'] = array('class' => array('draggable'));
+ *   $form['table'][$row]['weight'] = array(
+ *     '#type' => 'textfield',
+ *     '#title' => t('Weight for @title', array('@title' => $thing['title'])),
+ *     '#title_display' => 'invisible',
+ *     '#size' => 4,
+ *     '#default_value' => $thing['weight'],
+ *     '#attributes' => array('class' => array('thing-weight')),
+ *   );
+ *
+ *   // The amount of link columns should be identical to the 'colspan'
+ *   // attribute in #header above.
+ *   $form['table'][$row]['edit'] = array(
+ *     '#type' => 'link',
+ *     '#title' => t('Edit'),
+ *     '#href' => 'thing/' . $row . '/edit',
+ *   );
+ * }
+ * @endcode
+ *
+ * @param $element
+ *   A structured array containing two sub-levels of elements.
+ *
+ * @see system_element_info()
+ * @see theme_table()
+ * @see drupal_process_attached()
+ * @see drupal_add_tabledrag()
+ */
+function drupal_pre_render_table($element) {
+  foreach (element_children($element) as $first) {
+    $row = array('data' => array());
+    // Apply attributes of first-level elements as table row attributes.
+    if (isset($element[$first]['#attributes'])) {
+      $row += $element[$first]['#attributes'];
+    }
+    // Turn second-level elements into table row columns.
+    foreach (element_children($element[$first]) as $second) {
+      // Assign the element by reference, so any potential changes to the
+      // original element are taken over.
+      $row['data'][] = array('data' => &$element[$first][$second]);
+    }
+    $element['#rows'][] = $row;
+  }
+
+  // Take over $element['#id'] as HTML ID attribute, if not already set.
+  if (!isset($element['#attributes']['id']) && !empty($element['#id'])) {
+    $element['#attributes']['id'] = $element['#id'];
+  }
+
+  // If the custom #attached][tabledrag] is set and there is a HTML ID, convert
+  // it into #attached][drupal_add_tabledrag] and inject the HTML ID as first
+  // callback argument.
+  if (isset($element['#attached']['tabledrag']) && isset($element['#attributes']['id'])) {
+    $element['#attached']['drupal_add_tabledrag'] = $element['#attached']['tabledrag'];
+    foreach ($element['#attached']['drupal_add_tabledrag'] as &$args) {
+      array_unshift($args, $element['#attributes']['id']);
+    }
+    unset($element['#attached']['tabledrag']);
+  }
+
+  return $element;
+}
+
+/**
  * Renders the page, including all theming.
  *
  * @param $page
Index: modules/menu/menu.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.admin.inc,v
retrieving revision 1.90
diff -u -p -r1.90 menu.admin.inc
--- modules/menu/menu.admin.inc	20 Oct 2010 07:40:59 -0000	1.90
+++ modules/menu/menu.admin.inc	3 Nov 2010 21:25:40 -0000
@@ -7,38 +7,82 @@
  */
 
 /**
- * Menu callback which shows an overview page of all the custom menus and their descriptions.
+ * Form constructor for administrative menu list.
  */
-function menu_overview_page() {
-  $result = db_query("SELECT * FROM {menu_custom} ORDER BY title", array(), array('fetch' => PDO::FETCH_ASSOC));
-  $header = array(t('Title'), array('data' => t('Operations'), 'colspan' => '3'));
-  $rows = array();
-  foreach ($result as $menu) {
-    $row = array(theme('menu_admin_overview', array('title' => $menu['title'], 'name' => $menu['menu_name'], 'description' => $menu['description'])));
-    $row[] = array('data' => l(t('list links'), 'admin/structure/menu/manage/' . $menu['menu_name']));
-    $row[] = array('data' => l(t('edit menu'), 'admin/structure/menu/manage/' . $menu['menu_name'] . '/edit'));
-    $row[] = array('data' => l(t('add link'), 'admin/structure/menu/manage/' . $menu['menu_name'] . '/add'));
-    $rows[] = $row;
+function menu_admin_menus($form, &$form_state) {
+  $menus = db_query("SELECT * FROM {menu_custom} ORDER BY weight", array(), array('fetch' => PDO::FETCH_ASSOC));
+
+  $form['menus'] = array(
+    '#tree' => TRUE,
+    '#type' => 'table',
+    '#header' => array(t('Title'), t('Weight'), array('data' => t('Operations'), 'colspan' => '3')),
+    '#attached' => array(
+      'tabledrag' => array(array('order', 'sibling', 'menu-weight')),
+    ),
+  );
+
+  foreach ($menus as $menu) {
+    $name = $menu['menu_name'];
+
+    $form_state['menus'][$name] = $menu;
+    $form['menus'][$name]['#weight'] = $menu['weight'];
+    $form['menus'][$name]['#attributes'] = array('class' => array('draggable'));
+
+    $form['menus'][$name]['menu'] = array(
+      '#type' => 'item',
+      '#title' => check_plain($menu['title']),
+      '#description' => filter_xss_admin($menu['description']),
+    );
+    $form['menus'][$name]['weight'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Weight for @title', array('@title' => $menu['title'])),
+      '#title_display' => 'invisible',
+      '#size' => 4,
+      '#default_value' => $menu['weight'],
+      '#attributes' => array('class' => array('menu-weight')),
+    );
+    $form['menus'][$name]['list'] = array(
+      '#type' => 'link',
+      '#title' => t('list links'),
+      '#href' => 'admin/structure/menu/manage/' . $menu['menu_name'],
+    );
+    $form['menus'][$name]['edit'] = array(
+      '#type' => 'link',
+      '#title' => t('edit menu'),
+      '#href' => 'admin/structure/menu/manage/' . $menu['menu_name'] . '/edit',
+    );
+    $form['menus'][$name]['add'] = array(
+      '#type' => 'link',
+      '#title' => t('add link'),
+      '#href' => 'admin/structure/menu/manage/' . $menu['menu_name'] . '/add',
+    );
   }
 
-  return theme('table', array('header' => $header, 'rows' => $rows));
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save order'),
+    '#submit' => array('menu_admin_menus_order_submit'),
+  );
+
+  return $form;
 }
 
 /**
- * Returns HTML for a menu title and description for the menu overview page.
- *
- * @param $variables
- *   An associative array containing:
- *   - title: The menu's title.
- *   - description: The menu's description.
- *
- * @ingroup themeable
+ * Form submit handler for menu_admin_menus() to save the order of menus.
  */
-function theme_menu_admin_overview($variables) {
-  $output = check_plain($variables['title']);
-  $output .= '<div class="description">' . filter_xss_admin($variables['description']) . '</div>';
+function menu_admin_menus_order_submit($form, &$form_state) {
+  $active = array();
+  foreach ($form_state['values']['menus'] as $menu_name => $menu) {
+    // Save the new menu weights.
+    $menu += $form_state['menus'][$menu_name];
+    menu_save($menu);
 
-  return $output;
+    $active[$menu_name] = $menu['weight'];
+  }
+  // Update the order of active menus for menu_set_active_menu_names().
+  asort($active);
+  variable_set('menu_default_active_menus', array_keys($active));
 }
 
 /**
Index: modules/menu/menu.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.install,v
retrieving revision 1.26
diff -u -p -r1.26 menu.install
--- modules/menu/menu.install	23 Aug 2010 23:38:06 -0000	1.26
+++ modules/menu/menu.install	3 Nov 2010 16:54:46 -0000
@@ -34,8 +34,17 @@ function menu_schema() {
         'description' => 'Menu description.',
         'translatable' => TRUE,
       ),
+      'weight' => array(
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'description' => 'Menu weight.',
+      ),
     ),
     'primary key' => array('menu_name'),
+    'indexes' => array(
+      'name_weight' => array('menu_name', 'weight'),
+    ),
   );
 
   return $schema;
@@ -70,3 +79,15 @@ function menu_uninstall() {
   menu_rebuild();
 }
 
+/**
+ * Add {menu_custom}.weight column.
+ */
+function menu_update_7000() {
+  db_add_field('menu_custom', 'weight', array(
+    'type' => 'int',
+    'not null' => TRUE,
+    'default' => 0,
+    'description' => 'Menu weight.',
+  ));
+  db_add_index('menu_custom', 'name_weight', array('menu_name', 'weight'));
+}
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.233
diff -u -p -r1.233 menu.module
--- modules/menu/menu.module	24 Sep 2010 00:37:43 -0000	1.233
+++ modules/menu/menu.module	3 Nov 2010 17:24:08 -0000
@@ -29,12 +29,20 @@ function menu_help($path, $arg) {
       $output .= '<dd>' . t('After you have created a menu, you must enable and position the associated block on the <a href="@blocks">Blocks administration page</a>.', array('@blocks' => url('admin/structure/block'))) . '</dd>';
       $output .= '</dl>';
       return $output;
+
+    case 'admin/structure/menu':
+      $output = '';
+      $output .= '<p>' . t('Re-order the menus to control which menu should be active when a link is found in more than one.') . '</p>';
+      if (module_exists('block')) {
+        $output .= '<p>' . t('Each menu has a corresponding block that is managed on the <a href="@blocks">Blocks administration page</a>.', array(
+          '@blocks' => url('admin/structure/block'),
+        )) . '</p>';
+      }
+      return $output;
+
     case 'admin/structure/menu/add':
       return '<p>' . t('You can enable the newly-created block for this menu on the <a href="@blocks">Blocks administration page</a>.', array('@blocks' => url('admin/structure/block'))) . '</p>';
   }
-  if ($path == 'admin/structure/menu' && module_exists('block')) {
-    return '<p>' . t('Each menu has a corresponding block that is managed on the <a href="@blocks">Blocks administration page</a>.', array('@blocks' => url('admin/structure/block'))) . '</p>';
-  }
 }
 
 /**
@@ -55,7 +63,8 @@ function menu_menu() {
   $items['admin/structure/menu'] = array(
     'title' => 'Menus',
     'description' => 'Add new menus to your site, edit existing menus, and rename and reorganize menu links.',
-    'page callback' => 'menu_overview_page',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('menu_admin_menus'),
     'access callback' => 'user_access',
     'access arguments' => array('administer menu'),
     'file' => 'menu.admin.inc',
@@ -160,10 +169,6 @@ function menu_theme() {
       'file' => 'menu.admin.inc',
       'render element' => 'form',
     ),
-    'menu_admin_overview' => array(
-      'file' => 'menu.admin.inc',
-      'variables' => array('title' => NULL, 'name' => NULL, 'description' => NULL),
-    ),
   );
 }
 
@@ -229,7 +234,7 @@ function menu_load_all() {
       $custom_menus = $cached->data;
     }
     else {
-      $custom_menus = db_query('SELECT * FROM {menu_custom}')->fetchAllAssoc('menu_name', PDO::FETCH_ASSOC);
+      $custom_menus = db_query('SELECT * FROM {menu_custom} ORDER BY weight')->fetchAllAssoc('menu_name', PDO::FETCH_ASSOC);
       cache_set('menu_custom', $custom_menus, 'cache_menu');
     }
   }
@@ -256,6 +261,7 @@ function menu_save($menu) {
     ->fields(array(
       'title' => $menu['title'],
       'description' => $menu['description'],
+      'weight' => isset($menu['weight']) ? $menu['weight'] : 0,
     ))
     ->execute();
   menu_cache_clear_all();
@@ -750,3 +756,4 @@ function menu_get_menus($all = TRUE) {
   }
   return $custom_menus;
 }
+
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.986
diff -u -p -r1.986 system.module
--- modules/system/system.module	31 Oct 2010 22:02:20 -0000	1.986
+++ modules/system/system.module	3 Nov 2010 16:54:46 -0000
@@ -470,6 +470,12 @@ function system_element_info() {
   $types['link'] = array(
     '#pre_render' => array('drupal_pre_render_link', 'drupal_pre_render_markup'),
   );
+  $types['table'] = array(
+    '#header' => array(),
+    '#rows' => array(),
+    '#pre_render' => array('drupal_pre_render_table'),
+    '#theme' => 'table',
+  );
   $types['fieldset'] = array(
     '#collapsible' => FALSE,
     '#collapsed' => FALSE,
