Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.169
diff -u -p -r1.169 system.admin.inc
--- modules/system/system.admin.inc	5 Aug 2009 19:40:55 -0000	1.169
+++ modules/system/system.admin.inc	7 Aug 2009 12:24:13 -0000
@@ -134,21 +134,29 @@ function system_settings_overview() {
 
 /**
  * Menu callback; displays a listing of all themes.
- *
- * @ingroup forms
- * @see system_themes_form_submit()
  */
-function system_themes_form() {
+function system_themes_page() {
 
   $themes = system_get_theme_data();
   uasort($themes, 'system_sort_modules_by_info_name');
 
-  $status = array();
+  $theme_default = variable_get('theme_default', 'garland');
+  $theme_admin = variable_get('admin_theme', 0);
+  
   $incompatible_core = array();
   $incompatible_php = array();
 
-  foreach ($themes as $theme) {
-    $screenshot = NULL;
+  $groups = array('default', 'enabled', 'themes_admin', 'themes_disabled');
+  $theme_groups = array();
+
+  foreach ($themes as $key => $theme) {
+
+    // Add flags for admin and default.
+    $theme->is_admin    = ($theme->name == $theme_admin);
+    $theme->is_default  = ($theme->name == $theme_default);
+
+    // Identify theme screenshot.
+    $theme->screenshot = NULL;
     // Create a list which includes the current theme and all its base themes.
     if (isset($themes[$theme->name]->base_themes)) {
       $theme_keys = array_keys($themes[$theme->name]->base_themes) + array($theme->name);
@@ -159,82 +167,55 @@ function system_themes_form() {
     // Look for a screenshot in the current theme or in its closest ancestor.
     foreach (array_reverse($theme_keys) as $theme_key) {
       if (isset($themes[$theme_key]) && file_exists($themes[$theme_key]->info['screenshot'])) {
-        $screenshot = $themes[$theme_key]->info['screenshot'];
+        $theme->screenshot = $themes[$theme_key]->info['screenshot'];
         break;
       }
     }
-    $screenshot = $screenshot ? theme('image', $screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
-
-    $form[$theme->name]['screenshot'] = array('#markup' => $screenshot);
-    $form[$theme->name]['info'] = array(
-      '#type' => 'value',
-      '#value' => $theme->info,
-    );
-    $options[$theme->name] = $theme->info['name'];
-
-    if (!empty($theme->status) || $theme->name == variable_get('admin_theme', 0)) {
-      $form[$theme->name]['operations'] = array('#markup' => l(t('configure'), 'admin/appearance/settings/' . $theme->name) );
+    
+    if (!empty($theme->status) || $theme->is_admin) {
+      $theme->operations = array(
+        l(t('Configure'), 'admin/appearance/settings/' . $theme->name),
+        l(t('Disable'), 'admin/appearance/disable/' . $theme->name),
+      );
+      if (!$theme->is_default) {
+        $theme->operations[] = l(t('Set default'), 'admin/appearance/default/' . $theme->name);
+      }
     }
     else {
-      // Dummy element for drupal_render. Cleaner than adding a check in the theme function.
-      $form[$theme->name]['operations'] = array();
-    }
-    if (!empty($theme->status)) {
-      $status[] = $theme->name;
+      $theme->operations = array(
+        l(t('Enable'), 'admin/appearance/enable/' . $theme->name),
+        l(t('Set default'), 'admin/appearance/default/' . $theme->name),
+        l(t('Set admin theme'), 'admin/appearance/admin/' . $theme->name),
+      );
     }
-    else {
+    
+    if (empty($theme->status)) {
       // Ensure this theme is compatible with this version of core.
       // Require the 'content' region to make sure the main page
       // content has a common place in all themes.
-      if (!isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']))) {
-        $incompatible_core[] = $theme->name;
-      }
-      if (version_compare(phpversion(), $theme->info['php']) < 0) {
-        $incompatible_php[$theme->name] = $theme->info['php'];
-      }
+      $theme->incompatible_core = !isset($theme->info['core']) || ($theme->info['core'] != DRUPAL_CORE_COMPATIBILITY) || (!isset($theme->info['regions']['content']));
+      $theme->incompatible_php = version_compare(phpversion(), $theme->info['php']) < 0;
+    }
+    
+    // A theme can be in multiple groups. It can be default and admin theme
+    // at the same time for example. However, when a theme is both enabled
+    // and default, we do not list under the enabled themes.
+    if ($theme->is_default) {
+      $theme_groups['default'][] = $theme;    
+    }
+    if ($theme->is_admin) {
+      $theme_groups['admin'][] = $theme;    
+    }
+    if ($theme->status && !$theme->is_default) {
+      // Even include the admin theme if enabled.
+      $theme_groups['enabled'][] = $theme;    
+    }
+    if (!$theme->status) {
+      $theme_groups['disabled'][] = $theme;    
     }
   }
-
-  $form['status'] = array(
-    '#type' => 'checkboxes',
-    '#options' => array_fill_keys(array_keys($options), ''),
-    '#default_value' => $status,
-    '#incompatible_themes_core' => drupal_map_assoc($incompatible_core),
-    '#incompatible_themes_php' => $incompatible_php,
-  );
-  $form['theme_default'] = array(
-    '#type' => 'radios',
-    '#options' => array_fill_keys(array_keys($options), ''),
-    '#default_value' => variable_get('theme_default', 'garland'),
-  );
-
-  // Administration theme settings.
-  $form['admin_theme'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Administration theme'),
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-  );
-  $form['admin_theme']['admin_theme'] = array(
-    '#type' => 'select',
-    '#options' => array(0 => t('Default theme')) + $options,
-    '#title' => t('Administration theme'),
-    '#description' => t('Choose which theme the administration pages should display in. If you choose "Default theme" the administration pages will use the same theme as the rest of the site.'),
-    '#default_value' => variable_get('admin_theme', 0),
-  );
-  $form['admin_theme']['node_admin_theme'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Use administration theme for content editing'),
-    '#description' => t('Use the administration theme when editing existing posts or creating new ones.'),
-    '#default_value' => variable_get('node_admin_theme', '0'),
-  );
-
-  $form['buttons']['submit'] = array(
-    '#type' => 'submit',
-    '#value' => t('Save configuration'),
-  );
-
-  return $form;
+  
+  return theme('system_themes_page', $theme_groups);
 }
 
 /**
@@ -2162,58 +2143,54 @@ function theme_system_modules_uninstall(
 /**
  * Theme function for the system themes form.
  *
- * @param $form
- *   An associative array containing the structure of the form.
+ * @param $theme_groups
+ *   An associative array containing groups of themes.
  * @ingroup themeable
  */
-function theme_system_themes_form($form) {
-  foreach (element_children($form) as $key) {
-    // Only look for themes
-    if (!isset($form[$key]['info'])) {
+function theme_system_themes_page($theme_groups) {
+  $output = '<div id="system-themes-page">';
+  
+  // There are four possible theme groups.
+  $states = array(
+    'default' => t('Default theme'), 
+    'enabled' => format_plural(count($theme_groups['enabled']), 'Enabled theme', 'Enabled themes'),
+    'admin' => t('Admin theme'),
+    'disabled' => format_plural(count($theme_groups['disabled']), 'Disabled theme', 'Disabled themes'),
+  );
+  
+  foreach ($states as $state => $title) {
+    if (!count($theme_groups[$state])) {
+      // Skip this group of themes if no theme is there.
       continue;
     }
-
-    // Fetch info
-    $info = $form[$key]['info']['#value'];
-    // Localize theme description.
-    $description = t($info['description']);
-    // Make sure it is compatible and render the checkbox if so.
-    if (isset($form['status']['#incompatible_themes_core'][$key])) {
-      unset($form['status'][$key]);
-      $status = theme('image', 'misc/watchdog-error.png', t('incompatible'), t('Incompatible with this version of Drupal core'));
-      $description .= '<div class="incompatible">' . t('This version is incompatible with the !core_version version of Drupal core.', array('!core_version' => VERSION)) . '</div>';
-    }
-    elseif (isset($form['status']['#incompatible_themes_php'][$key])) {
-      unset($form['status'][$key]);
-      $status = theme('image', 'misc/watchdog-error.png', t('incompatible'), t('Incompatible with this version of PHP'));
-      $php_required = $form['status']['#incompatible_themes_php'][$key];
-      if (substr_count($php_required, '.') < 2) {
-        $php_required .= '.*';
+    // Start new theme group.
+    $output .= '<div class="system-themes-list system-themes-list-'. $state .'"><h2>'. $title .'</h2>';
+    
+    foreach($theme_groups[$state] as $theme) {
+      
+      // Theme the screenshot.
+      $screenshot = $theme->screenshot ? theme('image', $theme->screenshot, t('Screenshot for %theme theme', array('%theme' => $theme->info['name'])), '', array('class' => 'screenshot'), FALSE) : t('no screenshot');
+    
+      // Localize the theme description.
+      $description = t($theme->info['description']);
+
+      // Make sure to provide feedback on compatibility.
+      if (!empty($theme->incompatible_core)) {
+        $description .= '<div class="incompatible">' . t('This version is incompatible with the !core_version version of Drupal core.', array('!core_version' => VERSION)) . '</div>';
+      }
+      elseif (!empty($theme->inompatible_php)) {
+        if (substr_count($theme->info['php'], '.') < 2) {
+          $theme->info['php'] .= '.*';
+        }
+        $description .= '<div class="incompatible">' . t('This theme requires PHP version @php_required and is incompatible with PHP version !php_version.', array('@php_required' => $theme->info['php'], '!php_version' => phpversion())) . '</div>';
       }
-      $description .= '<div class="incompatible">' . t('This theme requires PHP version @php_required and is incompatible with PHP version !php_version.', array('@php_required' => $php_required, '!php_version' => phpversion())) . '</div>';
-    }
-    else {
-      $status = drupal_render($form['status'][$key]);
-    }
-
-    // Style theme info
-    $theme = '<div class="theme-info"><h2>' . $info['name'] . '</h2><div class="description">' . $description . '</div></div>';
 
-    // Build rows
-    $row = array();
-    $row[] = drupal_render($form[$key]['screenshot']);
-    $row[] = $theme;
-    $row[] = isset($info['version']) ? $info['version'] : '';
-    $row[] = array('data' => $status, 'align' => 'center');
-    if ($form['theme_default']) {
-      $row[] = array('data' => drupal_render($form['theme_default'][$key]), 'align' => 'center');
-      $row[] = array('data' => drupal_render($form[$key]['operations']), 'align' => 'center');
+      // Style theme info
+      $output .= '<div class="theme-selector">' . $screenshot . '<div class="theme-info"><h3>' . $theme->info['name'] . (isset($theme->info['version']) ? $theme->info['version'] : '') . '</h3><div class="description">' . $description . '</div><div class="operations">' . theme('item_list', $theme->operations) . '</div></div></div>';
     }
-    $rows[] = $row;
+    $output .= '</div>';
   }
-
-  $header = array(t('Screenshot'), t('Name'), t('Version'), t('Enabled'), t('Default'), t('Operations'));
-  $output = theme('table', $header, $rows);
-  $output .= drupal_render_children($form);
+  $output .= '</div>';
+    
   return $output;
 }
Index: modules/system/system.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.css,v
retrieving revision 1.58
diff -u -p -r1.58 system.css
--- modules/system/system.css	7 Aug 2009 05:34:08 -0000	1.58
+++ modules/system/system.css	7 Aug 2009 12:24:13 -0000
@@ -515,8 +515,47 @@ html.js .js-hide {
 /*
 ** Styles for the system themes page (admin/appearance)
 */
-#system-themes-form div.incompatible {
-  font-weight: bold;
+#block-system-main #system-themes-page h2 {
+  clear: both;
+  padding-top: 2em;
+  font-weight: normal;
+  text-transform: uppercase;
+}
+#system-themes-page .system-themes-list-default h2 {
+  padding-top: 0;
+}
+.theme-selector {
+  clear: both;
+  padding-top: 1em;
+}
+.theme-selector .screenshot {
+  float: left;
+  margin-right: 1em;
+}
+#block-system-main .theme-selector h3 {
+  padding-top: 2em;
+  font-weight: normal;
+}
+.system-themes-list-disabled .theme-selector {
+  width: 256px;
+  float: left;
+  clear: none;
+  padding: 1em 1em 1em 0;
+}
+.system-themes-list-disabled .theme-selector .screenshot {
+  padding-bottom: 0.5em;
+}
+.theme-selector .item-list li {
+  float: left;
+  padding: 0 0.7em 0 0.7em;
+  border-right: #cdcdcd 1px solid;
+}
+.theme-selector .item-list li.last {
+  padding: 0 0 0 0.7em;
+  border-right: none;
+}
+.theme-selector .item-list li.first {
+  padding: 0 0.7em 0 0;
 }
 
 /*
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.737
diff -u -p -r1.737 system.module
--- modules/system/system.module	5 Aug 2009 19:40:55 -0000	1.737
+++ modules/system/system.module	7 Aug 2009 12:24:14 -0000
@@ -150,8 +150,8 @@ function system_help($path, $arg) {
  */
 function system_theme() {
   return array_merge(drupal_common_theme(), array(
-    'system_themes_form' => array(
-      'arguments' => array('form' => NULL),
+    'system_themes_page' => array(
+      'arguments' => array('theme_groups' => NULL),
       'file' => 'system.admin.inc',
     ),
     'system_modules_fieldset' => array(
@@ -537,8 +537,7 @@ function system_menu() {
   // Appearance.
   $items['admin/appearance'] = array(
     'title' => 'Appearance',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('system_themes_form'),
+    'page callback' => 'system_themes_page',
     'access arguments' => array('administer site configuration'),
     'weight' => -6,
   );
Index: themes/garland/screenshot.png
===================================================================
RCS file: /cvs/drupal/drupal/themes/garland/screenshot.png,v
retrieving revision 1.1
diff -u -p -r1.1 screenshot.png
Binary files /tmp/cvsPwcrQs and screenshot.png differ
Index: themes/garland/minnelli/screenshot.png
===================================================================
RCS file: /cvs/drupal/drupal/themes/garland/minnelli/screenshot.png,v
retrieving revision 1.1
diff -u -p -r1.1 screenshot.png
Binary files /tmp/cvsCkCw6d and screenshot.png differ
Index: themes/seven/screenshot.png
===================================================================
RCS file: /cvs/drupal/drupal/themes/seven/screenshot.png,v
retrieving revision 1.1
diff -u -p -r1.1 screenshot.png
Binary files /tmp/cvswBjdnZ and screenshot.png differ
Index: themes/stark/screenshot.png
===================================================================
RCS file: /cvs/drupal/drupal/themes/stark/screenshot.png,v
retrieving revision 1.1
diff -u -p -r1.1 screenshot.png
Binary files /tmp/cvsNDsEEK and screenshot.png differ
