Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.85
diff -u -F^f -r1.85 module.inc
--- includes/module.inc	31 Aug 2006 22:12:15 -0000	1.85
+++ includes/module.inc	15 Sep 2006 00:24:47 -0000
@@ -130,7 +130,27 @@ function module_rebuild_cache() {
       db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, $file->info['description'], 'module', $file->filename, $file->status, $file->throttle, $bootstrap);
     }
   }
+  $files = _module_build_dependents($files);
+  return $files;
+}
 
+/**
+ * Find dependents; modules that are dependent on by other modules.
+ * Adds an array of dependents to the $file->info array.
+ * 
+ * @return 
+ *   The list of files array with dependents added where applicable.
+ */
+function _module_build_dependents($files) {
+  foreach ($files as $filename => $file) {
+    if (is_array($file->info['dependencies'])) {
+      foreach ($file->info['dependencies'] as $dependency) {
+        if (!empty($files[$dependency]) && is_array($files[$dependency]->info)) {
+          $files[$dependency]->info['dependents'][] = $filename;
+        }
+      }
+    }  	
+  }
   return $files;
 }
 
@@ -148,6 +168,16 @@ function module_rebuild_cache() {
  *   and variable_set() for that.
  * - You may not use double-quotes in a value.
  *
+ * Information stored in the module.info file:
+ * name - The real name of the module for display purposes.
+ * description - A brief description of the module.
+ * dependencies - A space delimited list of the short names (shortname) of other modules this module depends on.  
+ * 
+ * Example of .info file:
+ *   name = Forum
+ *   description = Enables threaded discussions about general topics.
+ *   dependencies = taxonomy comment
+ * 
  * @param $filename
  *   The file we are parsing.  Accepts file with relative or absolute path.
  * @return
@@ -159,6 +189,9 @@ function _module_parse_info_file($filena
   if (file_exists($filename)) {
     $info = parse_ini_file($filename);
   }
+  if (isset($info['dependencies'])) {
+    $info['dependencies'] = explode(" ", $info['dependencies']);
+  }  
   return $info;
 }
 
Index: modules/forum/forum.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.info,v
retrieving revision 1.1
diff -u -F^f -r1.1 forum.info
--- modules/forum/forum.info	31 Aug 2006 20:22:35 -0000	1.1
+++ modules/forum/forum.info	15 Sep 2006 00:24:55 -0000
@@ -1,4 +1,4 @@
 ; $Id: forum.info,v 1.1 2006/08/31 20:22:35 dries Exp $
 name = Forum
 description = Enables threaded discussions about general topics.
-
+dependencies = taxonomy comment
Index: modules/system/admin.css
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/admin.css,v
retrieving revision 1.7
diff -u -F^f -r1.7 admin.css
--- modules/system/admin.css	6 Sep 2006 08:35:59 -0000	1.7
+++ modules/system/admin.css	15 Sep 2006 00:24:58 -0000
@@ -39,6 +39,16 @@
   padding-right: 4px;
 }
 
+div.admin-missing, div.admin-required {
+  font-size: 0.9em;
+  color: #444;
+}
+
+input.modules-button {
+  width: 70px;
+  cursor: pointer;
+  font-size:95%;
+}
 /**
  * Formatting for status report
  */
@@ -63,3 +73,4 @@
 table.system-status-report tr.ok th {
   background-image: url('../../misc/watchdog-ok.png');
 }
+
Index: modules/system/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.module,v
retrieving revision 1.369
diff -u -F^f -r1.369 system.module
--- modules/system/system.module	8 Sep 2006 23:13:00 -0000	1.369
+++ modules/system/system.module	15 Sep 2006 00:24:59 -0000
@@ -187,8 +187,7 @@ function system_menu($may_cache) {
       'title' => t('modules'),
       'description' => t('Enable or disable add-on modules for your site.'),
       'weight' => -10,
-      'callback' => 'drupal_get_form',
-      'callback arguments' => array('system_modules'),
+      'callback' => 'system_modules',
       'access' => $access);
 
     // Settings:
@@ -1217,116 +1216,174 @@ function system_themes_submit($form_id, 
 }
 
 /**
- * Menu callback; displays a listing of all modules.
+ * Helper function to reduce code. Provides a form that is a button 
+ * keyed to the module.
  */
-function system_modules() {
-  // Get current list of modules
-  $files = module_rebuild_cache();
-
-  foreach ($files as $filename => $file) {
-    $info = $file->info;
-    $form['name'][$file->name] = array('#value' => $info['name']);
-    $form['description'][$file->name] = array('#value' => t($info['description']));
-    $options[$file->name] = '';
-    if ($file->status) {
-      $status[] = $file->name;
-    }
-    if ($file->throttle) {
-      $throttle[] = $file->name;
-    }
-  }
+function system_module_form($module, $metadata, $type) {
 
-  // Handle status checkboxes, including overriding the generated
-  // checkboxes for required modules.
-  $form['status'] = array('#type' => 'checkboxes', '#default_value' => $status, '#options' => $options);
-  $required = array('block', 'filter', 'node', 'system', 'user', 'watchdog');
-  foreach ($required as $require) {
-    $form['status'][$require] = array('#type' => 'hidden', '#value' => 1, '#suffix' => t('required'));
-  }
-
-  /**
-   * Handle throttle checkboxes, including overriding the generated checkboxes for required modules.
-   */
-  if (module_exists('throttle')) {
-    $form['throttle'] = array('#type' => 'checkboxes', '#default_value' => $throttle, '#options' => $options);
-    $throttle_required = array_merge($required, array('throttle'));
-    foreach ($throttle_required as $require) {
-      $form['throttle'][$require] = array('#type' => 'hidden', '#value' => 0, '#suffix' => t('required'));
-    }
-  }
-
-  $form['buttons']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => $type,
+    '#attributes' => array('class' => 'modules-button'),
+  );
+  
+  $form['metadata'] = array(
+    '#type' => 'value',
+    '#value' => $metadata,
+    '#attributes' => array('class' => 'modules-button'),
+  );
+  
+  $form['#submit']['system_module_form_submit'] = array();
 
   return $form;
 }
 
-function theme_system_modules($form) {
-  foreach (element_children($form['name']) as $key) {
-    $row = array();
-    $row[] = array('data' => drupal_render($form['status'][$key]), 'align' => 'center');
-
-    if (module_exists('throttle')) {
-      $row[] = array('data' => drupal_render($form['throttle'][$key]), 'align' => 'center');
+/**
+ * Hook hook_forms; to set the callback function of module button forms.
+ */
+function system_forms() {
+  static $forms = array();
+  if (!$forms) {
+    $files = system_listing('\.module$', 'modules', 'name', 0);
+    foreach ($files as $file) {
+      $forms["system_module_form_$file->name"]['callback'] = 'system_module_form';
     }
-    $row[] = drupal_render($form['name'][$key]);
-    $row[] = drupal_render($form['description'][$key]);
-    $rows[] = $row;
   }
+  return $forms;
+}
 
-  $header = array(t('Enabled'));
-  if (module_exists('throttle')) {
-    $header[] = t('Throttle');
-  }
-  $header[] = t('Name');
-  $header[] = t('Description');
+/**
+ * Menu callback; provides module enable/disable interface.
+ *
+ * Modules can be enabled or disabled and set for throttling if the throttle module is enabled.
+ * The list of modules gets populated by module.info files, which contain each module's name, 
+ * description and dependencies.
+ * \sa _module_parse_info_file for information on module.info descriptors.
+ *
+ * Dependency checking is performed to ensure that a module cannot be enabled if the module has 
+ * disabled dependencies and also to ensure that the module cannot be disabled if the module has 
+ * enabled dependents.
+ *
+ * @return
+ *   The form array.
+ */
 
-  $output = theme('table', $header, $rows);
-  $output .= drupal_render($form);
-  return $output;
-}
+function system_modules() {
+  // Get current list of modules.
+  $files = module_rebuild_cache();
 
+  $header = array(
+    array('data' => t('Operations'), 
+          'header' => TRUE, 
+          'class' => 'modules-heading operations', 
+    ),
+    array('data' => t('Name'), 
+          'header' => TRUE, 
+          'class' => 'modules-heading name',
+    ),
+    array('data' => t('Description'), 
+          'header' => TRUE, 
+          'class' => 'modules-heading related',
+    ),
+  );  
 
-function system_modules_submit($form_id, $form_values) {
-  include_once './includes/install.inc';
-  $new_modules = array();
+  // Array for disabling checkboxes in callback system_module_disable.
+  $disabled = array();
+  $rows = array();
+  // Traverse the files retrieved and build the form.
+  foreach ($files as $filename => $file) {
+    $can_change = TRUE;
+    $description = t($file->info['description']);
+    
+    $dependencies = array();
+    // Check for missing dependencies and add dependency information.
+    if (is_array($file->info['dependencies'])) {
+      foreach ($file->info['dependencies'] as $dependency) {
+        if (!isset($files[$dependency]) || !$files[$dependency]->status) {
+          $disabled[] = $filename;
+          if (isset($files[$dependency])) {
+            $dependencies[] = $files[$dependency]->info['name'] . t(' (disabled)');
+            $can_change = FALSE;
+          } 
+          else {
+            $dependencies[] = drupal_ucfirst($dependency) . t(' (missing)');
+            $can_change = FALSE;
+          } 
+        }
+        else {
+          $dependencies[] = $files[$dependency]->info['name'] . t(' (enabled)');
+        }
+      }
 
-  // Enable/disable modules that have already been installed
-  foreach ($form_values['status'] as $key => $choice) {
-    if ($choice) {
-      if (drupal_get_installed_schema_version($key) == SCHEMA_UNINSTALLED) {
-        $new_modules[] = $key;
+      if (!empty($dependencies)) {
+        $description .= t('<div class="admin-missing">Dependencies: @dependencies</div>', array('@dependencies' => implode(', ', $dependencies)));
       }
-      else {
-        module_enable($key);
+    }
+
+    // Check for enabled dependents and add dependent information.
+    $dependents = array();
+    if (is_array($file->info['dependents'])){
+      foreach ($file->info['dependents'] as $dependent) {
+        if ($files[$dependent]->status == 1) {
+          $dependents[] = $files[$dependent]->info['name'] . t(' (enabled)');         
+          $can_change = FALSE;
+        }
+        else {
+          $dependents[] = $files[$dependent]->info['name'] . t(' (disabled)');
+        }          
       }
     }
+
+    if (!empty($dependents)){
+      $description .= t('<div class="admin-required">Required by: @required</div>', array('@required' => implode(', ', $dependents)));
+    }
+    
+    // Add information for required modules.    
+    if (in_array($filename, array('block', 'filter', 'node', 'system', 'user', 'watchdog'))){
+      $description .= t('<div class="admin-required">Required for Drupal core</div>');
+      $can_change = FALSE;
+    }
+
+    // Calculate which buttons to display.
+    if (!$can_change){
+      $button = '';	
+    } 
+    else if ($file->status) {  	
+      $button = drupal_get_form("system_module_form_$filename", $filename, $file, t('Disable'));
+    } 
+    else if ($file->schema_version == -1) {
+      $button = drupal_get_form("system_module_form_$filename", $filename, $file, t('Install'));
+    } 
     else {
-      module_disable($key);
+      $button = drupal_get_form("system_module_form_$filename", $filename, $file, t('Enable'));
     }
-  }
+    
+    $rows[] = array($button, $file->info['name'], $description); 
+  } 
 
-  module_list(TRUE, FALSE);
+  return theme('table', $header, $rows, array('class' => 'modules-table'));
+}
 
-  // Install new modules
-  foreach ($new_modules as $module) {
-    if (drupal_check_module($module)) {
-      drupal_install_module($module);
-    }
-  }
+/**
+ * Submit callback; handles modules form submission.
+ */
+function system_module_form_submit($form_id, $form_values) {
+  include_once './includes/install.inc';
 
-  if (is_array($form_values['throttle'])) {
-    foreach ($form_values['throttle'] as $key => $choice) {
-      if ($choice) {
-        db_query("UPDATE {system} SET throttle = 1 WHERE type = 'module' and name = '%s'", $key);
-      }
-    }
+  if ($form_values['op'] == t('Install')) {
+    drupal_install_module($form_values['metadata']->name);
+    drupal_set_message(t('%module installed.', array('%module' => $form_values['metadata']->info['name'])));
+  } 
+  else if ($form_values['op'] == t('Enable')) {
+    module_enable($form_values['metadata']->name);
+    drupal_set_message(t('%module enabled.', array('%module' => $form_values['metadata']->info['name'])));
+  }
+  else {
+    module_disable($form_values['metadata']->name);
+    drupal_set_message(t('%module disabled.', array('%module' => $form_values['metadata']->info['name'])));
   }
-
   menu_rebuild();
   node_types_rebuild();
-
-  drupal_set_message(t('The configuration options have been saved.'));
-  return 'admin/settings/modules';
 }
 
 /**
