diff --git a/core/modules/contact/contact.admin.inc b/core/modules/contact/contact.admin.inc
index 7b1c90b..7bf3219 100644
--- a/core/modules/contact/contact.admin.inc
+++ b/core/modules/contact/contact.admin.inc
@@ -6,52 +6,135 @@
  */
 
 /**
- * Page callback: Lists contact categories.
+ * Form constructor for categories overview form.
  *
  * @see contact_menu()
  */
-function contact_category_list() {
-  $header = array(
-    t('Category'),
-    t('Recipients'),
-    t('Selected'),
-    array('data' => t('Operations'), 'colspan' => 2),
-  );
-  $rows = array();
-
+function contact_category_overview($form) {
   // Get all the contact categories from the database.
   $categories = db_select('contact', 'c')
     ->addTag('translatable')
-    ->fields('c', array('cid', 'category', 'recipients', 'selected'))
+    ->fields('c', array('cid', 'category', 'recipients', 'selected', 'weight'))
     ->orderBy('weight')
     ->orderBy('category')
     ->execute()
     ->fetchAll();
 
+  $form['categories'] = array(
+    '#categories' => array(),
+    '#tree' => TRUE,
+    '#header' => array(
+      t('Category'),
+      t('Recipients'),
+      t('Selected'),
+      t('Weight'),
+      array('data' => t('Operations'), 'colspan' => 2),
+    ),
+    '#theme' => 'contact_category_overview_form_table',
+  );
   // Loop through the categories and add them to the table.
   foreach ($categories as $category) {
+    $form['categories']['#categories'][$category->cid] = $category;
+    $form['categories'][$category->cid]['category']['#markup'] = check_plain($category->category);
+    $form['categories'][$category->cid]['recipients']['#markup'] = check_plain($category->recipients);
+    $form['categories'][$category->cid]['selected'] = array(
+      '#type' => 'radio',
+      '#parents' => array('category_selected'),
+      '#title' => t('Set @title as default', array('@title' => $category->category)),
+      '#title_display' => 'invisible',
+      '#return_value' => $category->cid,
+      '#default_value' => ($category->selected ? $category->cid : NULL),
+      '#id' => 'edit-category-selected-' . $category->cid,
+    );
+    if ($category->selected) {
+      $form['categories']['#category_selected'] = $category->selected;
+    }
+    $form['categories'][$category->cid]['#weight'] = $category->weight;
+    $form['categories'][$category->cid]['weight'] = array(
+      '#type' => 'weight',
+      '#title' => t('Weight for @title', array('@title' => $category->category)),
+      '#title_display' => 'invisible',
+      '#default_value' => $category->weight,
+    );
+    $form['categories'][$category->cid]['edit'] = array(
+      '#type' => 'link',
+      '#title' => t('Edit'),
+      '#href' => 'admin/structure/contact/edit/' . $category->cid);
+    $form['categories'][$category->cid]['delete'] = array(
+      '#type' => 'link',
+      '#title' => t('Delete'),
+      '#href' => 'admin/structure/contact/delete/' . $category->cid,
+    );
+  }
+
+  $form['categories']['#empty'] = t('No categories available.');
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+
+  return $form;
+}
+
+/**
+ * Returns HTML for the list of contact categories form.
+ *
+ * @param $variables
+ *   An associative array containing:
+ *   - form: A render element representing the form.
+ *
+ * @ingroup themeable
+ */
+function theme_contact_category_overview_form_table($variables) {
+  $form = $variables['form'];
+
+  $rows = array();
+  foreach (element_children($form) as $cid) {
+    $form[$cid]['weight']['#attributes']['class'] = array('contact-category-order-weight');
     $rows[] = array(
-      check_plain($category->category),
-      check_plain($category->recipients),
-      ($category->selected ? t('Yes') : t('No')),
-      l(t('Edit'), 'admin/structure/contact/edit/' . $category->cid),
-      l(t('Delete'), 'admin/structure/contact/delete/' . $category->cid),
+      'data' => array(
+        drupal_render($form[$cid]['category']),
+        drupal_render($form[$cid]['recipients']),
+        drupal_render($form[$cid]['selected']),
+        drupal_render($form[$cid]['weight']),
+        drupal_render($form[$cid]['edit']),
+        drupal_render($form[$cid]['delete']),
+      ),
+      'class' => array('draggable'),
     );
   }
 
-  if (!$rows) {
-    $rows[] = array(array(
-      'data' => t('No categories available.'),
-      'colspan' => 5,
-    ));
+  $output = theme('table', array(
+    'header' => $form['#header'],
+    'rows' => $rows,
+    'attributes' => array('id' => 'contact-category-order'),
+    'empty' => $form['#empty'],
+  ));
+  $output .= drupal_render_children($form);
+
+  drupal_add_tabledrag('contact-category-order', 'order', 'sibling', 'contact-category-order-weight');
+
+  return $output;
+}
+
+/**
+ * Form submission handler for contact_category_overview().
+ */
+function contact_category_overview_submit($form, &$form_state) {
+  $categories = $form['categories']['#categories'];
+  foreach ($categories as $cid => $category) {
+    db_update('contact')
+      ->fields(array(
+        'weight' => $form_state['values']['categories'][$cid]['weight'],
+        'selected' => ($cid == $form_state['values']['category_selected'] ? 1 : 0),
+      ))
+      ->condition('cid', $cid)
+      ->execute();
   }
 
-  $build['category_table'] = array(
-    '#theme' => 'table',
-    '#header' => $header,
-    '#rows' => $rows,
-  );
-  return $build;
+  drupal_set_message(t('Configuration saved.'));
 }
 
 /**
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 48c12d9..faee9c5 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -58,7 +58,8 @@ function contact_menu() {
   $items['admin/structure/contact'] = array(
     'title' => 'Contact form',
     'description' => 'Create a system contact form and set up categories for the form to use.',
-    'page callback' => 'contact_category_list',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('contact_category_overview'),
     'access arguments' => array('administer contact forms'),
     'file' => 'contact.admin.inc',
   );
@@ -257,3 +258,15 @@ function contact_form_user_admin_settings_alter(&$form, &$form_state) {
     '#default_value' => variable_get('contact_default_status', 1),
   );
 }
+
+/**
+ * Implements hook_theme().
+ */
+function contact_theme() {
+  return array(
+    'contact_category_overview_form_table' => array(
+      'render element' => 'form',
+      'file' => 'contact.admin.inc',
+    ),
+  );
+}
