? 884730-formatter_settings_0.patch
? 884730-formatter_settings_1.patch
? 884730.patch
Index: modules/field/views_handler_field_field.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/views/modules/field/Attic/views_handler_field_field.inc,v
retrieving revision 1.1.2.3
diff -u -p -r1.1.2.3 views_handler_field_field.inc
--- modules/field/views_handler_field_field.inc	5 Jun 2010 06:53:31 -0000	1.1.2.3
+++ modules/field/views_handler_field_field.inc	29 Sep 2010 21:05:01 -0000
@@ -29,6 +29,41 @@ function _field_view_formatter_options($
 }
 
 /**
+ * Loads a dummy instance that we can use to get the formatter settings latter on.
+ */
+function _field_view_get_instance($field) {
+  // Find any valid instance of this field.
+  $fields = field_info_fields();
+  $entities = (array) $fields[$field['field_name']]['bundles'];
+  $bundle = '';
+  foreach ($entities as $entity_type => $bundles) {
+    $bundle = array_shift($bundles);
+    break;
+  }
+  // No instances of this field? Can't do anything more.
+  if (empty($bundle)) {
+    return;
+  }
+  $instance = field_info_instance($entity_type, $field['field_name'], $bundle);
+
+  return $instance;
+}
+
+/**
+ * Adds a #states attribute to each passed element,
+ * to be shown when the $type formatter is selected.
+ */
+function _field_view_add_states(&$elements, $type) {
+  foreach ($elements as $key => $element) {
+    $elements[$key]['#states'] = array(
+      'visible' => array(
+        ':input[name="options[type]"]' => array('value' => $type),
+      ),
+    );
+  }
+}
+
+/**
  * A field that displays fields.
  */
 class views_handler_field_field extends views_handler_field {
@@ -42,19 +77,58 @@ class views_handler_field_field extends 
     return parent::query();
   }
 
+  /**
+   * We need to declare defaults for all possible formatter settings,
+   * in order for them to be saveable later on.
+   */
   function option_definition() {
-    $options = parent::option_definition();
-
     $field = field_info_field($this->definition['field_name']);
     $field_type = field_info_field_types($field['type']);
+    $instance = _field_view_get_instance($field);
 
+    $options = parent::option_definition();
     $options['type'] = array(
       'default' => $field_type['default_formatter'],
     );
+    $options['formatters'] = array(
+      'contains' => array(),
+    );
+
+    // We can't continue without a field instance
+    if (!$instance) {
+      return;
+    }
+
+    // Prefill any kind of formatter settings into options
+    // because we will not know which formatter the user will change.
+    $formatters = _field_view_formatter_options($field['type']);
+    $view_mode = 'default';
+    $formatter_types = field_info_formatter_types();
+    foreach ($formatters as $formatter => $name) {
+      $info = $formatter_types[$formatter];
+      $form_function = $info['module'] . '_field_formatter_settings_form';
+      $settings_function = $info['module'] . '_field_formatter_info';
+
+      if (!function_exists($form_function) || !function_exists($settings_function)) {
+        continue;
+      }
+
+      $settings_info = $settings_function();
+      if (!isset($settings_info[$formatter]['settings']) || count($settings_info[$formatter]['settings']) < 1) {
+        continue;
+      }
+
+      foreach ($settings_info[$formatter]['settings'] as $settings_key => $value) {
+        $options['formatters']['contains'][$formatter]['contains'][$settings_key]['default'] = $value;
+      }
+    }
 
     return $options;
   }
 
+  /**
+   * Loads and renders the formatter selector, as well as settings for each one.
+   */
   function options_form(&$form, &$form_state) {
     parent::options_form($form, $form_state);
 
@@ -67,11 +141,42 @@ class views_handler_field_field extends 
       '#options' => $formatters,
       '#default_value' => $this->options['type'],
     );
+
+    $instance = _field_view_get_instance($field);
+
+    // We can't continue without a field instance
+    if (!$instance) {
+      return;
+    }
+
+    $view_mode = 'default';
+    $formatter_types = field_info_formatter_types();
+    foreach ($formatters as $formatter => $name) {
+      $info = $formatter_types[$formatter];
+      $form_function = $info['module'] . '_field_formatter_settings_form';
+      $settings_function = $info['module'] . '_field_formatter_info';
+
+      if (!function_exists($form_function) || !function_exists($settings_function)) {
+        continue;
+      }
+
+      $settings_info = $settings_function();
+      if (!isset($settings_info[$formatter]['settings']) || count($settings_info[$formatter]['settings']) < 1) {
+        continue;
+      }
+
+      // Replaces the formatter defaults them with the settings stored in Views
+      // (if any), and generates the settings form shown for this formatter.
+      $default_settings = $settings_info[$formatter]['settings'];
+      $instance['display'][$view_mode]['settings'] = array_merge($default_settings, $this->options['formatters'][$formatter]);
+      $form['formatters'][$formatter] = $form_function($field, $instance, $view_mode, array(), $form_state);
+      _field_view_add_states($form['formatters'][$formatter], $formatter);
+    }
   }
 
   /**
    * Loads the objects providing the field information necessary to render the
-   *   field in the View.
+   * field in the View.
    */
   function pre_render(&$values) {
     static $entity_type_map;
@@ -108,19 +213,25 @@ class views_handler_field_field extends 
     }
   }
 
+  /**
+   * Renders a field using the specified formatter settings.
+   */
   function render($values) {
     if (isset($values->_field_cache[$this->field_alias])) {
       // Prepare arguments for rendering based on the objects cached in the
       // pre-render phase and the display options for this field.
       $entity_type = $values->_field_cache[$this->field_alias]['entity_type'];
       $object = $values->_field_cache[$this->field_alias]['object'];
+      $type = $this->options['type'];
 
       $display = array(
-        'type' => $this->options['type'],
         'label' => 'hidden',
+        'type' => $type,
+        'settings' => isset($this->options['formatters'][$type]) ? $this->options['formatters'][$type] : array(),
       );
 
-      return drupal_render(field_view_field($entity_type, $object, $this->definition['field_name'], $display));
+      $render_array = field_view_field($entity_type, $object, $this->definition['field_name'], $display);
+      return drupal_render($render_array);
     }
     else {
       return '';
