Index: menu_breadcrumb.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/menu_breadcrumb/menu_breadcrumb.module,v
retrieving revision 1.7
diff -u -p -r1.7 menu_breadcrumb.module
--- menu_breadcrumb.module	5 Oct 2009 22:01:27 -0000	1.7
+++ menu_breadcrumb.module	9 Oct 2009 02:07:37 -0000
@@ -51,20 +51,110 @@ function menu_breadcrumb_menu() {
 }
 
 /**
+ * Get the menu selection configuration.
+ *
+ * @return
+ *   The menu selection/weight array.
+ */
+function _menu_breadcrumb_get_menus() {
+  static $menus;
+  if (!isset($menus)) {
+    // The default selections, if we have yet to configure the module.
+    if ( is_null(variable_get('menu_breadcrumb_menus', NULL)) ) {
+      $disabled_by_default = array( 
+        'devel', 
+        'admin_menu',
+      ) ;
+      // consider hook here allowing modules to disable their menu
+      // by default
+      foreach( menu_get_names() as $menu_name ) {
+        if ( in_array( $menu_name, $disabled_by_default ) ) {
+          $default_menus[$menu_name] = array(
+            'selected' => 0,
+            'weight'   => 10,
+          ) ;
+        }
+        else {
+          $default_menus[$menu_name] = array(
+            'selected' => 1,
+            'weight'   => -10,
+          ) ;
+        }
+      }
+    }
+    // Fetch stored settings, and merge in any previously-unknown menus
+    $menus = variable_get('menu_breadcrumb_menus', $default_menus);
+    foreach (menu_get_names() as $menu_name) {
+      if (!array_key_exists($menu_name, $menus)) {
+        $menus[$menu_name] = array('selected' => $menus['zero_row']['selected'], 'weight' => 0);
+      }
+    }
+    uasort($menus, '_menu_breadcrumb_sort'); // sort by weight
+  }
+  return $menus;
+}
+
+
+/**
+ * Sort-by-weight comparison.
+ */
+function _menu_breadcrumb_sort($menu1, $menu2) {
+  $menu1_weight = !empty($menu1['weight']) ? $menu1['weight'] : 0;
+  $menu2_weight = !empty($menu2['weight']) ? $menu2['weight'] : 0;
+  if ($menu1_weight == $menu2_weight) {
+    return 0;
+  }
+  return ($menu1_weight < $menu2_weight) ? -1 : 1;
+}
+
+
+/**
+ * Get the menu/selection list.
+ *
+ * @return
+ *   An array indicating the selection status of each menu.
+ */
+function menu_breadcrumb_menu_list() {
+  static $list;
+
+  if (!isset($list)) {
+    $menus = _menu_breadcrumb_get_menus();
+
+    $list = array();
+    foreach ($menus as $name => $menu) {
+      $list[$name] = (bool) $menu['selected'];
+    }
+
+    // Enable other modules to dynamically modify the menu list
+    // (for example, to make the order depend upon the current
+    // user's language preference)
+    if ($hook = module_invoke_all('menu_breadcrumb_menu_list', $list)) {
+      $list = $hook;
+    }
+  }
+
+  return $list;
+}
+
+
+/**
  * Implementation of hook_init().
+ * 
+ * Set the active menu according to the current path.
  */
 function menu_breadcrumb_init() {
   if (variable_get('menu_breadcrumb_determine_menu', 1)) {
-    $menu_list = variable_get('menu_breadcrumb_menus', array('admin_menu', 'devel'));
-    $filter = variable_get('menu_breadcrumb_menus_filter', 'blacklist');
+    $menu_list = menu_breadcrumb_menu_list();
     $menu_item = menu_get_item();
     $result = db_query("SELECT mlid, menu_name FROM {menu_links} WHERE link_path = '%s'", $menu_item['href']);
+    $menus = array();
     while ($menu_link = db_fetch_array($result)) {
-      // @see http://www.php.net/manual/en/function.in-array.php#86695
-      $menu_in_list = in_array($menu_link['menu_name'], $menu_list, TRUE);
-      if ( ( $filter == 'whitelist' && $menu_in_list ) ||
-           ( $filter == 'blacklist' && !$menu_in_list ) ) {
-        menu_set_active_menu_name($menu_link['menu_name']);
+      $menus[$menu_link['menu_name']] = TRUE;
+    }
+
+    foreach ($menu_list as $menu_name => $selected) {
+      if ($selected && array_key_exists($menu_name, $menus)) {
+        menu_set_active_menu_name($menu_name);
         break;
       }
     }
@@ -92,9 +182,11 @@ function menu_breadcrumb_init() {
  * Menu breadcrumb admin settings form.
  *
  * @return
- * The settings form used by Menu breadcrumb.
+ *   The settings form used by Menu breadcrumb.
  */
 function menu_breadcrumb_admin_settings_form() {
+  $form['#submit'][] = 'menu_breadcrumb_admin_settings_form_submit';
+
   $form['menu_breadcrumb_determine_menu'] = array(
     '#type' => 'checkbox',
     '#title' => t('Use menu the page belongs to for the breadcrumb.'),
@@ -123,30 +215,149 @@ function menu_breadcrumb_admin_settings_
     '#default_value' => variable_get('menu_breadcrumb_hide_on_single_item', 0),
   );
 
-  $include_exclude_description = 'Use this to specify which menus are used to generate breadcrumbs. ' ;
   $form['include_exclude'] = array( 
     '#type' => 'fieldset',
     '#title' => t('Include / Exclude Menus'),
-    '#description' => t($include_exclude_description),
+    '#description' => t('Menus are used to generate breadcrumbs in the order they appear here, and only if enabled.'),
   ) ;
 
-  $form['include_exclude']['menu_breadcrumb_menus_filter'] = array(
-    '#type' => 'radios',
-    '#title' => t('Menu filter'),
-    '#options' => array(
-      'blacklist' => t('Blacklist - Menu items will never be chosen from the menus selected below.'),
-      'whitelist' => t('Whitelist - Menu items will only be chosen from the menus selected below.'),
-    ),
-    '#default_value' => variable_get('menu_breadcrumb_menus_filter', 'blacklist'),
+  // Orderable list of menu selections
+  $form['include_exclude']['menu_breadcrumb_menus'] = array(
+    '#tree' => TRUE,
+    '#theme' => 'menu_breadcrumb_menus_table',
   );
 
-  $form['include_exclude']['menu_breadcrumb_menus'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Menu list'),
-    '#description' => t('Select which menus to apply the blacklist / whitelist to.'),
-    '#options' => drupal_map_assoc(menu_get_names()),
-    '#default_value' => variable_get('menu_breadcrumb_menus', array('admin_menu', 'devel')),
+  $menus = _menu_breadcrumb_get_menus();
+  $weight_delta = count($menus);
+
+  $opts_enabled = array( 
+    1 => t('Enabled'),
+    0 => t('Disabled'),
+  ) ;
+  foreach ($menus as $menu_name => $menu) {
+    $form['include_exclude']['menu_breadcrumb_menus'][$menu_name] = array(
+      'selected' => array(
+        '#type' => 'select',
+        '#title' => '',
+        '#options' => $opts_enabled,
+        '#default_value' => $menu['selected'],
+      ),
+      'label' => array(
+        '#value' => $menu_name,
+      ),
+      'weight' => array(
+        '#type' => 'weight',
+        '#default_value' => !empty($menu['weight']) ? (int) $menu['weight'] : 0,
+        '#delta' => $weight_delta,
+      ),
+    );
+  }
+
+  $default_value = ( $menus['zero_row']['selected'] ) ;
+  $form['include_exclude']['menu_breadcrumb_menus']['zero_row'] = array(
+    'selected' => array(
+      '#type' => 'select',
+      '#title' => '',
+      '#options' => $opts_enabled,
+      '#default_value' => $default_value,
+    ),
+    'label' => array(
+      '#value' => $menu_name,
+    ),
+    'weight' => array(
+      '#type' => 'weight',
+      '#default_value' => 0,
+      '#delta' => $weight_delta,
+    ),
   );
+  
+  $form['include_exclude']['description'] = array(
+   '#value' => '<p class="description"><strong>Menu Default</strong> is not a real menu - it defines the position and enabled status for newly created menus. If Menu Default is enabled, Menu Breadcrumb will automatically include new menus when looking for breadcrumbs. If Menu Default is disabled, new menus will not be used for breadcrumbs until the specific menu is enabled here.</p>',
+  ) ;
 
   return system_settings_form($form);
+}
+
+
+/**
+ * Form submission handler.
+ *
+ * Adjust all weights with respect to zero_row before
+ * system_settings_form_submit() saves the values.
+ */
+function menu_breadcrumb_admin_settings_form_submit($form, &$form_state) {
+  $menus =& $form_state['values']['menu_breadcrumb_menus'];
+  $zero_weight = $menus['zero_row']['weight'];
+  foreach (array_keys($menus) as $menu) {
+    $menus[$menu]['weight'] -= $zero_weight;
+  }
+}
+
+/**
+ * Implementation of hook_theme().
+ */
+function menu_breadcrumb_theme() {
+  return array(
+    'menu_breadcrumb_menus_table' => array(
+      'arguments' => array('element' => NULL),
+    ),
+  );
+}
+
+/**
+ * Theme a drag-to-reorder table of menu selection checkboxes.
+ */
+function theme_menu_breadcrumb_menus_table($element) {
+  drupal_add_tabledrag('menu-breadcrumb-menus', 'order', 'sibling', 'menu-weight');
+
+  $header = array(
+    t('Menu list:'),
+    t('Weight:'),
+  );
+
+  // Separate out the draggable weight:0 row
+  $element['zero_row']['weight']['#attributes']['class'] = 'menu-weight';
+  $zero_row = array(
+    'data' => array(
+      drupal_render($element['zero_row']['selected']) .
+      t( 'Menu Default (see below)' ),
+      drupal_render($element['zero_row']['weight']),
+    ),
+    'class' => 'draggable',
+  );
+  unset($element['zero_row']);
+
+  // Generate table of draggable menu names
+  $rows = array();
+  foreach (element_children($element) as $menu_name) {
+    if ($zero_row) {
+      if ($element[$menu_name]['weight']['#value'] >= 0) {
+        $rows[] = $zero_row;
+        $zero_row = FALSE;
+        ++$element[$menu_name]['weight']['#value'];
+      }
+    }
+    else {
+      ++$element[$menu_name]['weight']['#value'];
+    }
+    $element[$menu_name]['weight']['#attributes']['class'] = 'menu-weight';
+    $row = array();
+    $menu = menu_load($menu_name);
+    if ( !isset($menu['title']) || empty($menu['title']) ) {
+      $menu['title'] = $menu_name ;
+    }
+    $row[] = drupal_render($element[$menu_name]['selected']).$menu['title'];
+    $row[] = drupal_render($element[$menu_name]['weight']);
+    $rows[] = array(
+      'data' => $row,
+      'class' => 'draggable',
+    );
+  }
+
+  // all weights were > 0; add the zero row at the end.
+  if ($zero_row) {
+    $rows[] = $zero_row;
+  }
+
+  return theme('table', $header, $rows, array('id' => 'menu-breadcrumb-menus'));
 }
\ No newline at end of file
